blob: c7cc8afcea44303dd90afa8f2d414d76e392b744 [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
7#include <base/logging.h>
Darin Petkov1272a432011-11-10 15:53:37 +01008#include <base/stl_util-inl.h>
9#include <base/string_number_conversions.h>
Darin Petkovac635a82012-01-10 16:51:58 +010010#include <base/stringprintf.h>
Darin Petkov20c13ec2011-11-09 15:07:15 +010011#include <chromeos/dbus/service_constants.h>
12#include <mm/mm-modem.h>
Darin Petkov1272a432011-11-10 15:53:37 +010013#include <mobile_provider.h>
Darin Petkovdaf43862011-10-27 11:37:28 +020014
Darin Petkov3cfbf212011-11-21 16:02:09 +010015#include "shill/adaptor_interfaces.h"
Darin Petkovae0c64e2011-11-15 15:50:27 +010016#include "shill/cellular_service.h"
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050017#include "shill/error.h"
Darin Petkov721ac932011-11-16 15:43:09 +010018#include "shill/property_accessor.h"
Darin Petkovdaf43862011-10-27 11:37:28 +020019#include "shill/proxy_factory.h"
20
Darin Petkovb05315f2011-11-07 10:14:25 +010021using std::string;
22
Darin Petkovdaf43862011-10-27 11:37:28 +020023namespace shill {
24
Darin Petkovac635a82012-01-10 16:51:58 +010025// static
26unsigned int CellularCapabilityGSM::friendly_service_name_id_ = 0;
27
Darin Petkov1272a432011-11-10 15:53:37 +010028const char CellularCapabilityGSM::kNetworkPropertyAccessTechnology[] =
29 "access-tech";
30const char CellularCapabilityGSM::kNetworkPropertyID[] = "operator-num";
31const char CellularCapabilityGSM::kNetworkPropertyLongName[] = "operator-long";
32const char CellularCapabilityGSM::kNetworkPropertyShortName[] =
33 "operator-short";
34const char CellularCapabilityGSM::kNetworkPropertyStatus[] = "status";
Darin Petkovae0c64e2011-11-15 15:50:27 +010035const char CellularCapabilityGSM::kPhoneNumber[] = "*99#";
36const char CellularCapabilityGSM::kPropertyAccessTechnology[] =
37 "AccessTechnology";
Darin Petkov63138a92012-02-06 14:09:15 +010038const char CellularCapabilityGSM::kPropertyEnabledFacilityLocks[] =
39 "EnabledFacilityLocks";
Darin Petkov721ac932011-11-16 15:43:09 +010040const char CellularCapabilityGSM::kPropertyUnlockRequired[] = "UnlockRequired";
41const char CellularCapabilityGSM::kPropertyUnlockRetries[] = "UnlockRetries";
Darin Petkov1272a432011-11-10 15:53:37 +010042
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050043CellularCapabilityGSM::CellularCapabilityGSM(Cellular *cellular,
44 ProxyFactory *proxy_factory)
45 : CellularCapability(cellular, proxy_factory),
Darin Petkov1272a432011-11-10 15:53:37 +010046 task_factory_(this),
Darin Petkov184c54e2011-11-15 12:44:39 +010047 registration_state_(MM_MODEM_GSM_NETWORK_REG_STATUS_UNKNOWN),
Darin Petkovae0c64e2011-11-15 15:50:27 +010048 access_technology_(MM_MODEM_GSM_ACCESS_TECH_UNKNOWN),
Darin Petkov0a4dfeb2011-11-18 19:36:13 +010049 home_provider_(NULL),
Darin Petkov1272a432011-11-10 15:53:37 +010050 scanning_(false),
51 scan_interval_(0) {
Darin Petkov5f316f62011-11-18 12:10:26 +010052 VLOG(2) << "Cellular capability constructed: GSM";
Darin Petkov1272a432011-11-10 15:53:37 +010053 PropertyStore *store = cellular->mutable_store();
Darin Petkov184c54e2011-11-15 12:44:39 +010054 store->RegisterConstString(flimflam::kSelectedNetworkProperty,
55 &selected_network_);
Darin Petkov1272a432011-11-10 15:53:37 +010056 store->RegisterConstStringmaps(flimflam::kFoundNetworksProperty,
57 &found_networks_);
58 store->RegisterConstBool(flimflam::kScanningProperty, &scanning_);
59 store->RegisterUint16(flimflam::kScanIntervalProperty, &scan_interval_);
Darin Petkov63138a92012-02-06 14:09:15 +010060 HelpRegisterDerivedKeyValueStore(
61 flimflam::kSIMLockStatusProperty,
62 &CellularCapabilityGSM::SimLockStatusToProperty,
63 NULL);
Darin Petkov3cfbf212011-11-21 16:02:09 +010064 store->RegisterConstStringmaps(flimflam::kCellularApnListProperty,
65 &apn_list_);
Darin Petkov0d06f7d2012-02-03 13:08:19 +010066 scanning_supported_ = true;
Darin Petkov1272a432011-11-10 15:53:37 +010067}
Darin Petkovdaf43862011-10-27 11:37:28 +020068
Darin Petkov63138a92012-02-06 14:09:15 +010069KeyValueStore CellularCapabilityGSM::SimLockStatusToProperty(Error */*error*/) {
70 KeyValueStore status;
71 status.SetBool(flimflam::kSIMLockEnabledProperty, sim_lock_status_.enabled);
72 status.SetString(flimflam::kSIMLockTypeProperty, sim_lock_status_.lock_type);
73 status.SetUint(flimflam::kSIMLockRetriesLeftProperty,
74 sim_lock_status_.retries_left);
75 return status;
Darin Petkov721ac932011-11-16 15:43:09 +010076}
77
Darin Petkov63138a92012-02-06 14:09:15 +010078void CellularCapabilityGSM::HelpRegisterDerivedKeyValueStore(
Darin Petkov721ac932011-11-16 15:43:09 +010079 const string &name,
Darin Petkov63138a92012-02-06 14:09:15 +010080 KeyValueStore(CellularCapabilityGSM::*get)(Error *error),
81 void(CellularCapabilityGSM::*set)(
82 const KeyValueStore &value, Error *error)) {
83 cellular()->mutable_store()->RegisterDerivedKeyValueStore(
Darin Petkov721ac932011-11-16 15:43:09 +010084 name,
Darin Petkov63138a92012-02-06 14:09:15 +010085 KeyValueStoreAccessor(
86 new CustomAccessor<CellularCapabilityGSM, KeyValueStore>(
Darin Petkov721ac932011-11-16 15:43:09 +010087 this, get, set)));
88}
89
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050090void CellularCapabilityGSM::StartModem()
91{
92 CellularCapability::StartModem();
Darin Petkovcb547732011-11-09 13:55:26 +010093 card_proxy_.reset(
94 proxy_factory()->CreateModemGSMCardProxy(this,
Darin Petkovdaf43862011-10-27 11:37:28 +020095 cellular()->dbus_path(),
96 cellular()->dbus_owner()));
Darin Petkov184c54e2011-11-15 12:44:39 +010097 network_proxy_.reset(
98 proxy_factory()->CreateModemGSMNetworkProxy(this,
Darin Petkovdaf43862011-10-27 11:37:28 +020099 cellular()->dbus_path(),
100 cellular()->dbus_owner()));
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500101 MultiStepAsyncCallHandler *call_handler =
102 new MultiStepAsyncCallHandler(cellular()->dispatcher());
103 call_handler->AddTask(task_factory_.NewRunnableMethod(
104 &CellularCapabilityGSM::EnableModem, call_handler));
105
106 call_handler->AddTask(task_factory_.NewRunnableMethod(
107 &CellularCapabilityGSM::Register, call_handler));
108
109 call_handler->AddTask(task_factory_.NewRunnableMethod(
110 &CellularCapabilityGSM::GetModemStatus, call_handler));
111
112 call_handler->AddTask(task_factory_.NewRunnableMethod(
113 &CellularCapabilityGSM::GetIMEI, call_handler));
114
115 call_handler->AddTask(task_factory_.NewRunnableMethod(
116 &CellularCapabilityGSM::GetIMSI, call_handler));
117
118 call_handler->AddTask(task_factory_.NewRunnableMethod(
119 &CellularCapabilityGSM::GetSPN, call_handler));
120
121 call_handler->AddTask(task_factory_.NewRunnableMethod(
122 &CellularCapabilityGSM::GetMSISDN, call_handler));
123
124 call_handler->AddTask(task_factory_.NewRunnableMethod(
125 &CellularCapabilityGSM::GetProperties, call_handler));
126
127 call_handler->AddTask(task_factory_.NewRunnableMethod(
128 &CellularCapabilityGSM::GetModemInfo, call_handler));
129
130 call_handler->AddTask(task_factory_.NewRunnableMethod(
131 &CellularCapabilityGSM::GetRegistrationState,
132 call_handler));
133 call_handler->PostNextTask();
Darin Petkovdaf43862011-10-27 11:37:28 +0200134}
135
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500136void CellularCapabilityGSM::StopModem() {
Darin Petkov721ac932011-11-16 15:43:09 +0100137 VLOG(2) << __func__;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500138 CellularCapability::StopModem();
Darin Petkov721ac932011-11-16 15:43:09 +0100139 card_proxy_.reset();
140 network_proxy_.reset();
141}
142
Darin Petkov5f316f62011-11-18 12:10:26 +0100143void CellularCapabilityGSM::OnServiceCreated() {
Darin Petkov31332412012-01-28 01:50:02 +0100144 // If IMSI is available, base the service's storage identifier on it.
145 if (!imsi_.empty()) {
146 cellular()->service()->SetStorageIdentifier(
Darin Petkovdd3e8662012-02-03 13:16:20 +0100147 string(flimflam::kTypeCellular) + "_" +
148 cellular()->address() + "_" + imsi_);
Darin Petkov31332412012-01-28 01:50:02 +0100149 }
Darin Petkovb9c99332012-01-12 13:13:00 +0100150 cellular()->service()->SetActivationState(
Darin Petkov5f316f62011-11-18 12:10:26 +0100151 flimflam::kActivationStateActivated);
152 UpdateServingOperator();
153}
154
Darin Petkovae0c64e2011-11-15 15:50:27 +0100155void CellularCapabilityGSM::UpdateStatus(const DBusPropertiesMap &properties) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500156 if (ContainsKey(properties, kPropertyIMSI)) {
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100157 SetHomeProvider();
Darin Petkovae0c64e2011-11-15 15:50:27 +0100158 }
159}
160
161void CellularCapabilityGSM::SetupConnectProperties(
162 DBusPropertiesMap *properties) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500163 (*properties)[kConnectPropertyPhoneNumber].writer().append_string(
Darin Petkovae0c64e2011-11-15 15:50:27 +0100164 kPhoneNumber);
165 // TODO(petkov): Setup apn and "home_only".
166}
167
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500168void CellularCapabilityGSM::GetIMEI(AsyncCallHandler *call_handler){
Darin Petkovcb547732011-11-09 13:55:26 +0100169 VLOG(2) << __func__;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500170 if (imei_.empty()) {
171 card_proxy_->GetIMEI(call_handler, kTimeoutDefault);
172 } else {
173 VLOG(2) << "Already have IMEI " << imei_;
174 CompleteOperation(call_handler);
Darin Petkovcb547732011-11-09 13:55:26 +0100175 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500176}
177
178void CellularCapabilityGSM::GetIMSI(AsyncCallHandler *call_handler){
179 VLOG(2) << __func__;
180 if (imsi_.empty()) {
181 card_proxy_->GetIMSI(call_handler, kTimeoutDefault);
182 } else {
183 VLOG(2) << "Already have IMSI " << imsi_;
184 CompleteOperation(call_handler);
Darin Petkovcb547732011-11-09 13:55:26 +0100185 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500186}
187
188void CellularCapabilityGSM::GetSPN(AsyncCallHandler *call_handler){
189 VLOG(2) << __func__;
Darin Petkovae0c64e2011-11-15 15:50:27 +0100190 if (spn_.empty()) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500191 card_proxy_->GetSPN(call_handler, kTimeoutDefault);
192 } else {
193 VLOG(2) << "Already have SPN " << spn_;
194 CompleteOperation(call_handler);
Darin Petkovcb547732011-11-09 13:55:26 +0100195 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500196}
197
198void CellularCapabilityGSM::GetMSISDN(AsyncCallHandler *call_handler){
199 VLOG(2) << __func__;
200 if (mdn_.empty()) {
201 card_proxy_->GetMSISDN(call_handler, kTimeoutDefault);
202 } else {
203 VLOG(2) << "Already have MSISDN " << mdn_;
204 CompleteOperation(call_handler);
Darin Petkovcb547732011-11-09 13:55:26 +0100205 }
206}
207
Darin Petkov3e509242011-11-10 14:46:44 +0100208void CellularCapabilityGSM::GetSignalQuality() {
209 VLOG(2) << __func__;
210 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Darin Petkov184c54e2011-11-15 12:44:39 +0100211 uint32 strength = network_proxy_->GetSignalQuality();
Darin Petkov3e509242011-11-10 14:46:44 +0100212 cellular()->HandleNewSignalQuality(strength);
213}
214
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500215void CellularCapabilityGSM::GetRegistrationState(
216 AsyncCallHandler *call_handler) {
Darin Petkov184c54e2011-11-15 12:44:39 +0100217 VLOG(2) << __func__;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500218 network_proxy_->GetRegistrationInfo(call_handler, kTimeoutDefault);
Darin Petkov184c54e2011-11-15 12:44:39 +0100219}
220
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500221void CellularCapabilityGSM::GetProperties(AsyncCallHandler *call_handler) {
Darin Petkov184c54e2011-11-15 12:44:39 +0100222 VLOG(2) << __func__;
Darin Petkov63138a92012-02-06 14:09:15 +0100223
Darin Petkov184c54e2011-11-15 12:44:39 +0100224 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
225 uint32 tech = network_proxy_->AccessTechnology();
Darin Petkovae0c64e2011-11-15 15:50:27 +0100226 SetAccessTechnology(tech);
Darin Petkov184c54e2011-11-15 12:44:39 +0100227 VLOG(2) << "GSM AccessTechnology: " << tech;
Darin Petkov63138a92012-02-06 14:09:15 +0100228
229 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
230 uint32 locks = card_proxy_->EnabledFacilityLocks();
231 sim_lock_status_.enabled = locks & MM_MODEM_GSM_FACILITY_SIM;
232 VLOG(2) << "GSM EnabledFacilityLocks: " << locks;
233
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500234 CompleteOperation(call_handler);
Darin Petkov184c54e2011-11-15 12:44:39 +0100235}
236
Darin Petkovac635a82012-01-10 16:51:58 +0100237string CellularCapabilityGSM::CreateFriendlyServiceName() {
238 VLOG(2) << __func__;
239 if (registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME &&
240 !cellular()->home_provider().GetName().empty()) {
241 return cellular()->home_provider().GetName();
242 }
243 if (!serving_operator_.GetName().empty()) {
244 return serving_operator_.GetName();
245 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500246 if (!carrier_.empty()) {
247 return carrier_;
Darin Petkovac635a82012-01-10 16:51:58 +0100248 }
249 if (!serving_operator_.GetCode().empty()) {
250 return "cellular_" + serving_operator_.GetCode();
251 }
252 return base::StringPrintf("GSMNetwork%u", friendly_service_name_id_++);
253}
254
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100255void CellularCapabilityGSM::SetHomeProvider() {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500256 VLOG(2) << __func__ << "(IMSI: " << imsi_
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100257 << " SPN: " << spn_ << ")";
258 // TODO(petkov): The test for NULL provider_db should be done by
259 // mobile_provider_lookup_best_match.
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500260 if (imsi_.empty() || !cellular()->provider_db()) {
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100261 return;
262 }
263 mobile_provider *provider =
264 mobile_provider_lookup_best_match(
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500265 cellular()->provider_db(), spn_.c_str(), imsi_.c_str());
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100266 if (!provider) {
267 VLOG(2) << "GSM provider not found.";
268 return;
269 }
270 home_provider_ = provider;
271 Cellular::Operator oper;
272 if (provider->networks) {
273 oper.SetCode(provider->networks[0]);
274 }
275 if (provider->country) {
276 oper.SetCountry(provider->country);
277 }
278 if (spn_.empty()) {
279 const char *name = mobile_provider_get_name(provider);
280 if (name) {
281 oper.SetName(name);
282 }
283 } else {
284 oper.SetName(spn_);
285 }
286 cellular()->set_home_provider(oper);
Darin Petkov3cfbf212011-11-21 16:02:09 +0100287 InitAPNList();
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100288}
289
Darin Petkovae0c64e2011-11-15 15:50:27 +0100290void CellularCapabilityGSM::UpdateOperatorInfo() {
291 VLOG(2) << __func__;
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100292 const string &network_id = serving_operator_.GetCode();
293 if (!network_id.empty()) {
294 VLOG(2) << "Looking up network id: " << network_id;
Darin Petkovae0c64e2011-11-15 15:50:27 +0100295 mobile_provider *provider =
296 mobile_provider_lookup_by_network(cellular()->provider_db(),
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100297 network_id.c_str());
Darin Petkovae0c64e2011-11-15 15:50:27 +0100298 if (provider) {
299 const char *provider_name = mobile_provider_get_name(provider);
300 if (provider_name && *provider_name) {
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100301 serving_operator_.SetName(provider_name);
302 if (provider->country) {
303 serving_operator_.SetCountry(provider->country);
304 }
305 VLOG(2) << "Operator name: " << serving_operator_.GetName()
306 << ", country: " << serving_operator_.GetCountry();
Darin Petkovae0c64e2011-11-15 15:50:27 +0100307 }
308 } else {
309 VLOG(2) << "GSM provider not found.";
310 }
311 }
312 UpdateServingOperator();
313}
314
315void CellularCapabilityGSM::UpdateServingOperator() {
316 VLOG(2) << __func__;
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100317 if (cellular()->service().get()) {
Darin Petkov9cb02682012-01-28 00:17:38 +0100318 cellular()->service()->SetServingOperator(serving_operator_);
Darin Petkovae0c64e2011-11-15 15:50:27 +0100319 }
Darin Petkovae0c64e2011-11-15 15:50:27 +0100320}
321
Darin Petkov3cfbf212011-11-21 16:02:09 +0100322void CellularCapabilityGSM::InitAPNList() {
323 VLOG(2) << __func__;
324 if (!home_provider_) {
325 return;
326 }
327 apn_list_.clear();
328 for (int i = 0; i < home_provider_->num_apns; ++i) {
329 Stringmap props;
330 mobile_apn *apn = home_provider_->apns[i];
331 if (apn->value) {
332 props[flimflam::kApnProperty] = apn->value;
333 }
334 if (apn->username) {
335 props[flimflam::kApnUsernameProperty] = apn->username;
336 }
337 if (apn->password) {
338 props[flimflam::kApnPasswordProperty] = apn->password;
339 }
340 // Find the first localized and non-localized name, if any.
341 const localized_name *lname = NULL;
342 const localized_name *name = NULL;
343 for (int j = 0; j < apn->num_names; ++j) {
344 if (apn->names[j]->lang) {
345 if (!lname) {
346 lname = apn->names[j];
347 }
348 } else if (!name) {
349 name = apn->names[j];
350 }
351 }
352 if (name) {
353 props[flimflam::kApnNameProperty] = name->name;
354 }
355 if (lname) {
356 props[flimflam::kApnLocalizedNameProperty] = lname->name;
357 props[flimflam::kApnLanguageProperty] = lname->lang;
358 }
359 apn_list_.push_back(props);
360 }
361 cellular()->adaptor()->EmitStringmapsChanged(
362 flimflam::kCellularApnListProperty, apn_list_);
363}
364
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500365void CellularCapabilityGSM::Register(AsyncCallHandler *call_handler) {
366 VLOG(2) << __func__ << " \"" << selected_network_ << "\"";
367 network_proxy_->Register(selected_network_, call_handler,
368 kTimeoutRegister);
Darin Petkov184c54e2011-11-15 12:44:39 +0100369}
370
371void CellularCapabilityGSM::RegisterOnNetwork(
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500372 const string &network_id, AsyncCallHandler *call_handler) {
373 VLOG(2) << __func__ << "(" << network_id << ")";
374 desired_network_ = network_id;
375 network_proxy_->Register(network_id, call_handler,
376 kTimeoutRegister);
377}
378
379void CellularCapabilityGSM::OnRegisterCallback(const Error &error,
380 AsyncCallHandler *call_handler) {
381 VLOG(2) << __func__ << "(" << error << ")";
382
383 if (error.IsSuccess()) {
384 selected_network_ = desired_network_;
385 desired_network_.clear();
386 CompleteOperation(call_handler);
387 return;
388 }
389 // If registration on the desired network failed,
390 // try to register on the home network.
391 if (!desired_network_.empty()) {
392 desired_network_.clear();
393 selected_network_.clear();
394 Register(call_handler);
395 return;
396 }
397 CompleteOperation(call_handler, error);
Darin Petkov184c54e2011-11-15 12:44:39 +0100398}
399
Darin Petkovb72cf402011-11-22 14:51:39 +0100400bool CellularCapabilityGSM::IsRegistered() {
401 return (registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME ||
402 registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING);
403}
404
Darin Petkovb05315f2011-11-07 10:14:25 +0100405void CellularCapabilityGSM::RequirePIN(
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500406 const string &pin, bool require, AsyncCallHandler *call_handler) {
407 VLOG(2) << __func__ << "(" << call_handler << ")";
408 card_proxy_->EnablePIN(pin, require, call_handler, kTimeoutDefault);
Darin Petkovb05315f2011-11-07 10:14:25 +0100409}
410
Darin Petkove5bc2cb2011-12-07 14:47:32 +0100411void CellularCapabilityGSM::EnterPIN(const string &pin,
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500412 AsyncCallHandler *call_handler) {
413 VLOG(2) << __func__ << "(" << call_handler << ")";
414 card_proxy_->SendPIN(pin, call_handler, kTimeoutDefault);
Darin Petkovb05315f2011-11-07 10:14:25 +0100415}
416
Darin Petkovc64fe5e2012-01-11 12:46:13 +0100417void CellularCapabilityGSM::UnblockPIN(const string &unblock_code,
418 const string &pin,
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500419 AsyncCallHandler *call_handler) {
420 VLOG(2) << __func__ << "(" << call_handler << ")";
421 card_proxy_->SendPUK(unblock_code, pin, call_handler,
422 kTimeoutDefault);
Darin Petkovb05315f2011-11-07 10:14:25 +0100423}
424
425void CellularCapabilityGSM::ChangePIN(
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500426 const string &old_pin, const string &new_pin,
427 AsyncCallHandler *call_handler) {
428 VLOG(2) << __func__ << "(" << call_handler << ")";
429 card_proxy_->ChangePIN(old_pin, new_pin, call_handler,
430 kTimeoutDefault);
Darin Petkovb05315f2011-11-07 10:14:25 +0100431}
432
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500433void CellularCapabilityGSM::Scan(AsyncCallHandler *call_handler) {
Darin Petkov1272a432011-11-10 15:53:37 +0100434 VLOG(2) << __func__;
435 // TODO(petkov): Defer scan requests if a scan is in progress already.
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500436 network_proxy_->Scan(call_handler, kTimeoutScan);
Darin Petkov1272a432011-11-10 15:53:37 +0100437}
438
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500439void CellularCapabilityGSM::OnScanCallback(const GSMScanResults &results,
440 const Error &error,
441 AsyncCallHandler *call_handler) {
442 VLOG(2) << __func__;
443 if (error.IsFailure()) {
444 CompleteOperation(call_handler, error);
445 return;
446 }
447 found_networks_.clear();
448 for (GSMScanResults::const_iterator it = results.begin();
449 it != results.end(); ++it) {
450 found_networks_.push_back(ParseScanResult(*it));
451 }
Darin Petkovb7828b02012-02-03 12:34:30 +0100452 cellular()->adaptor()->EmitStringmapsChanged(flimflam::kFoundNetworksProperty,
453 found_networks_);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500454 CompleteOperation(call_handler);
455}
456
457Stringmap CellularCapabilityGSM::ParseScanResult(const GSMScanResult &result) {
Darin Petkov1272a432011-11-10 15:53:37 +0100458 Stringmap parsed;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500459 for (GSMScanResult::const_iterator it = result.begin();
460 it != result.end(); ++it) {
Darin Petkov1272a432011-11-10 15:53:37 +0100461 // TODO(petkov): Define these in system_api/service_constants.h. The
462 // numerical values are taken from 3GPP TS 27.007 Section 7.3.
463 static const char * const kStatusString[] = {
464 "unknown",
465 "available",
466 "current",
467 "forbidden",
468 };
469 static const char * const kTechnologyString[] = {
470 flimflam::kNetworkTechnologyGsm,
471 "GSM Compact",
472 flimflam::kNetworkTechnologyUmts,
473 flimflam::kNetworkTechnologyEdge,
474 "HSDPA",
475 "HSUPA",
476 flimflam::kNetworkTechnologyHspa,
477 };
478 VLOG(2) << "Network property: " << it->first << " = " << it->second;
479 if (it->first == kNetworkPropertyStatus) {
480 int status = 0;
481 if (base::StringToInt(it->second, &status) &&
482 status >= 0 &&
483 status < static_cast<int>(arraysize(kStatusString))) {
484 parsed[flimflam::kStatusProperty] = kStatusString[status];
485 } else {
486 LOG(ERROR) << "Unexpected status value: " << it->second;
487 }
488 } else if (it->first == kNetworkPropertyID) {
489 parsed[flimflam::kNetworkIdProperty] = it->second;
490 } else if (it->first == kNetworkPropertyLongName) {
491 parsed[flimflam::kLongNameProperty] = it->second;
492 } else if (it->first == kNetworkPropertyShortName) {
493 parsed[flimflam::kShortNameProperty] = it->second;
494 } else if (it->first == kNetworkPropertyAccessTechnology) {
495 int tech = 0;
496 if (base::StringToInt(it->second, &tech) &&
497 tech >= 0 &&
498 tech < static_cast<int>(arraysize(kTechnologyString))) {
499 parsed[flimflam::kTechnologyProperty] = kTechnologyString[tech];
500 } else {
501 LOG(ERROR) << "Unexpected technology value: " << it->second;
502 }
503 } else {
504 LOG(WARNING) << "Unknown network property ignored: " << it->first;
505 }
506 }
507 // If the long name is not available but the network ID is, look up the long
508 // name in the mobile provider database.
509 if ((!ContainsKey(parsed, flimflam::kLongNameProperty) ||
510 parsed[flimflam::kLongNameProperty].empty()) &&
511 ContainsKey(parsed, flimflam::kNetworkIdProperty)) {
512 mobile_provider *provider =
513 mobile_provider_lookup_by_network(
514 cellular()->provider_db(),
515 parsed[flimflam::kNetworkIdProperty].c_str());
516 if (provider) {
517 const char *long_name = mobile_provider_get_name(provider);
518 if (long_name && *long_name) {
519 parsed[flimflam::kLongNameProperty] = long_name;
520 }
521 }
522 }
523 return parsed;
524}
525
Darin Petkovae0c64e2011-11-15 15:50:27 +0100526void CellularCapabilityGSM::SetAccessTechnology(uint32 access_technology) {
527 access_technology_ = access_technology;
528 if (cellular()->service().get()) {
Darin Petkovb72cf402011-11-22 14:51:39 +0100529 cellular()->service()->SetNetworkTechnology(GetNetworkTechnologyString());
Darin Petkovae0c64e2011-11-15 15:50:27 +0100530 }
531}
532
Darin Petkov20c13ec2011-11-09 15:07:15 +0100533string CellularCapabilityGSM::GetNetworkTechnologyString() const {
Darin Petkovb72cf402011-11-22 14:51:39 +0100534 switch (access_technology_) {
535 case MM_MODEM_GSM_ACCESS_TECH_GSM:
536 case MM_MODEM_GSM_ACCESS_TECH_GSM_COMPACT:
537 return flimflam::kNetworkTechnologyGsm;
538 case MM_MODEM_GSM_ACCESS_TECH_GPRS:
539 return flimflam::kNetworkTechnologyGprs;
540 case MM_MODEM_GSM_ACCESS_TECH_EDGE:
541 return flimflam::kNetworkTechnologyEdge;
542 case MM_MODEM_GSM_ACCESS_TECH_UMTS:
543 return flimflam::kNetworkTechnologyUmts;
544 case MM_MODEM_GSM_ACCESS_TECH_HSDPA:
545 case MM_MODEM_GSM_ACCESS_TECH_HSUPA:
546 case MM_MODEM_GSM_ACCESS_TECH_HSPA:
547 return flimflam::kNetworkTechnologyHspa;
548 case MM_MODEM_GSM_ACCESS_TECH_HSPA_PLUS:
549 return flimflam::kNetworkTechnologyHspaPlus;
550 default:
551 break;
Darin Petkov20c13ec2011-11-09 15:07:15 +0100552 }
553 return "";
554}
555
556string CellularCapabilityGSM::GetRoamingStateString() const {
Darin Petkov184c54e2011-11-15 12:44:39 +0100557 switch (registration_state_) {
Darin Petkov20c13ec2011-11-09 15:07:15 +0100558 case MM_MODEM_GSM_NETWORK_REG_STATUS_HOME:
559 return flimflam::kRoamingStateHome;
560 case MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING:
561 return flimflam::kRoamingStateRoaming;
562 default:
563 break;
564 }
565 return flimflam::kRoamingStateUnknown;
566}
567
Darin Petkovae0c64e2011-11-15 15:50:27 +0100568void CellularCapabilityGSM::OnModemManagerPropertiesChanged(
569 const DBusPropertiesMap &properties) {
570 uint32 access_technology = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN;
571 if (DBusProperties::GetUint32(properties,
572 kPropertyAccessTechnology,
573 &access_technology)) {
574 SetAccessTechnology(access_technology);
575 }
Darin Petkov63138a92012-02-06 14:09:15 +0100576 bool emit = false;
577 uint32 locks = 0;
578 if (DBusProperties::GetUint32(
579 properties, kPropertyEnabledFacilityLocks, &locks)) {
580 sim_lock_status_.enabled = locks & MM_MODEM_GSM_FACILITY_SIM;
581 emit = true;
582 }
583 if (DBusProperties::GetString(
584 properties, kPropertyUnlockRequired, &sim_lock_status_.lock_type)) {
585 emit = true;
586 }
587 if (DBusProperties::GetUint32(
588 properties, kPropertyUnlockRetries, &sim_lock_status_.retries_left)) {
589 emit = true;
590 }
591 if (emit) {
592 cellular()->adaptor()->EmitKeyValueStoreChanged(
593 flimflam::kSIMLockStatusProperty, SimLockStatusToProperty(NULL));
594 }
Darin Petkovae0c64e2011-11-15 15:50:27 +0100595}
596
Darin Petkov184c54e2011-11-15 12:44:39 +0100597void CellularCapabilityGSM::OnGSMNetworkModeChanged(uint32 /*mode*/) {
598 // TODO(petkov): Implement this.
599 NOTIMPLEMENTED();
600}
601
602void CellularCapabilityGSM::OnGSMRegistrationInfoChanged(
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500603 uint32 status, const string &operator_code, const string &operator_name,
604 const Error &error, AsyncCallHandler *call_handler) {
605 if (error.IsSuccess()) {
606 VLOG(2) << __func__ << ": regstate=" << status
607 << ", opercode=" << operator_code
608 << ", opername=" << operator_name;
609 registration_state_ = status;
610 serving_operator_.SetCode(operator_code);
611 serving_operator_.SetName(operator_name);
612 UpdateOperatorInfo();
613 cellular()->HandleNewRegistrationState();
614 }
615 CompleteOperation(call_handler, error);
Darin Petkov184c54e2011-11-15 12:44:39 +0100616}
617
618void CellularCapabilityGSM::OnGSMSignalQualityChanged(uint32 quality) {
619 cellular()->HandleNewSignalQuality(quality);
620}
621
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500622void CellularCapabilityGSM::OnGetIMEICallback(const string &imei,
623 const Error &error,
624 AsyncCallHandler *call_handler) {
625 if (error.IsSuccess()) {
626 VLOG(2) << "IMEI: " << imei;
627 imei_ = imei;
628 } else {
629 VLOG(2) << "GetIMEI failed - " << error;
630 }
631 CompleteOperation(call_handler, error);
632}
633
634void CellularCapabilityGSM::OnGetIMSICallback(const string &imsi,
635 const Error &error,
636 AsyncCallHandler *call_handler) {
637 if (error.IsSuccess()) {
638 VLOG(2) << "IMSI: " << imsi;
639 imsi_ = imsi;
640 SetHomeProvider();
641 } else {
642 VLOG(2) << "GetIMSI failed - " << error;
643 }
644 CompleteOperation(call_handler, error);
645}
646
647void CellularCapabilityGSM::OnGetSPNCallback(const string &spn,
648 const Error &error,
649 AsyncCallHandler *call_handler) {
650 if (error.IsSuccess()) {
651 VLOG(2) << "SPN: " << spn;
652 spn_ = spn;
653 SetHomeProvider();
654 } else {
655 VLOG(2) << "GetSPN failed - " << error;
656 }
657 // Ignore the error - it's not fatal.
658 CompleteOperation(call_handler);
659}
660
661void CellularCapabilityGSM::OnGetMSISDNCallback(
662 const string &msisdn, const Error &error, AsyncCallHandler *call_handler) {
663 if (error.IsSuccess()) {
664 VLOG(2) << "MSISDN: " << msisdn;
665 mdn_ = msisdn;
666 } else {
667 VLOG(2) << "GetMSISDN failed - " << error;
668 }
669 // Ignore the error - it's not fatal.
670 CompleteOperation(call_handler);
671}
672
673void CellularCapabilityGSM::OnPINOperationCallback(
674 const Error &error, AsyncCallHandler *call_handler) {
675 if (error.IsFailure())
676 VLOG(2) << "PIN operation failed - " << error;
677 else
678 VLOG(2) << "PIN operation complete";
679 CompleteOperation(call_handler, error);
680}
681
Darin Petkovdaf43862011-10-27 11:37:28 +0200682} // namespace shill