blob: e226f7646f48a20e96af3ffed51f96565a440f25 [file] [log] [blame]
Darin Petkovdaf43862011-10-27 11:37:28 +02001// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2// 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 Petkov20c13ec2011-11-09 15:07:15 +010010#include <chromeos/dbus/service_constants.h>
11#include <mm/mm-modem.h>
Darin Petkov1272a432011-11-10 15:53:37 +010012#include <mobile_provider.h>
Darin Petkovdaf43862011-10-27 11:37:28 +020013
Darin Petkov3cfbf212011-11-21 16:02:09 +010014#include "shill/adaptor_interfaces.h"
Darin Petkovae0c64e2011-11-15 15:50:27 +010015#include "shill/cellular_service.h"
Darin Petkov721ac932011-11-16 15:43:09 +010016#include "shill/property_accessor.h"
Darin Petkovdaf43862011-10-27 11:37:28 +020017#include "shill/proxy_factory.h"
18
Darin Petkov721ac932011-11-16 15:43:09 +010019using std::make_pair;
Darin Petkovb05315f2011-11-07 10:14:25 +010020using std::string;
21
Darin Petkovdaf43862011-10-27 11:37:28 +020022namespace shill {
23
Darin Petkov1272a432011-11-10 15:53:37 +010024const char CellularCapabilityGSM::kNetworkPropertyAccessTechnology[] =
25 "access-tech";
26const char CellularCapabilityGSM::kNetworkPropertyID[] = "operator-num";
27const char CellularCapabilityGSM::kNetworkPropertyLongName[] = "operator-long";
28const char CellularCapabilityGSM::kNetworkPropertyShortName[] =
29 "operator-short";
30const char CellularCapabilityGSM::kNetworkPropertyStatus[] = "status";
Darin Petkovae0c64e2011-11-15 15:50:27 +010031const char CellularCapabilityGSM::kPhoneNumber[] = "*99#";
32const char CellularCapabilityGSM::kPropertyAccessTechnology[] =
33 "AccessTechnology";
Darin Petkov721ac932011-11-16 15:43:09 +010034const char CellularCapabilityGSM::kPropertyUnlockRequired[] = "UnlockRequired";
35const char CellularCapabilityGSM::kPropertyUnlockRetries[] = "UnlockRetries";
Darin Petkov1272a432011-11-10 15:53:37 +010036
Darin Petkovdaf43862011-10-27 11:37:28 +020037CellularCapabilityGSM::CellularCapabilityGSM(Cellular *cellular)
Darin Petkovb05315f2011-11-07 10:14:25 +010038 : CellularCapability(cellular),
Darin Petkov1272a432011-11-10 15:53:37 +010039 task_factory_(this),
Darin Petkov184c54e2011-11-15 12:44:39 +010040 registration_state_(MM_MODEM_GSM_NETWORK_REG_STATUS_UNKNOWN),
Darin Petkovae0c64e2011-11-15 15:50:27 +010041 access_technology_(MM_MODEM_GSM_ACCESS_TECH_UNKNOWN),
Darin Petkov0a4dfeb2011-11-18 19:36:13 +010042 home_provider_(NULL),
Darin Petkov1272a432011-11-10 15:53:37 +010043 scanning_(false),
44 scan_interval_(0) {
Darin Petkov5f316f62011-11-18 12:10:26 +010045 VLOG(2) << "Cellular capability constructed: GSM";
Darin Petkov1272a432011-11-10 15:53:37 +010046 PropertyStore *store = cellular->mutable_store();
Darin Petkov184c54e2011-11-15 12:44:39 +010047 store->RegisterConstString(flimflam::kSelectedNetworkProperty,
48 &selected_network_);
Darin Petkov1272a432011-11-10 15:53:37 +010049 store->RegisterConstStringmaps(flimflam::kFoundNetworksProperty,
50 &found_networks_);
51 store->RegisterConstBool(flimflam::kScanningProperty, &scanning_);
52 store->RegisterUint16(flimflam::kScanIntervalProperty, &scan_interval_);
Darin Petkov721ac932011-11-16 15:43:09 +010053 HelpRegisterDerivedStrIntPair(flimflam::kSIMLockStatusProperty,
54 &CellularCapabilityGSM::SimLockStatusToProperty,
55 NULL);
Darin Petkov3cfbf212011-11-21 16:02:09 +010056 store->RegisterConstStringmaps(flimflam::kCellularApnListProperty,
57 &apn_list_);
Darin Petkov1272a432011-11-10 15:53:37 +010058}
Darin Petkovdaf43862011-10-27 11:37:28 +020059
Darin Petkov721ac932011-11-16 15:43:09 +010060StrIntPair CellularCapabilityGSM::SimLockStatusToProperty(Error */*error*/) {
61 return StrIntPair(make_pair(flimflam::kSIMLockTypeProperty,
62 sim_lock_status_.lock_type),
63 make_pair(flimflam::kSIMLockRetriesLeftProperty,
64 sim_lock_status_.retries_left));
65}
66
67void CellularCapabilityGSM::HelpRegisterDerivedStrIntPair(
68 const string &name,
69 StrIntPair(CellularCapabilityGSM::*get)(Error *),
70 void(CellularCapabilityGSM::*set)(const StrIntPair &, Error *)) {
71 cellular()->mutable_store()->RegisterDerivedStrIntPair(
72 name,
73 StrIntPairAccessor(
74 new CustomAccessor<CellularCapabilityGSM, StrIntPair>(
75 this, get, set)));
76}
77
Darin Petkov5f316f62011-11-18 12:10:26 +010078void CellularCapabilityGSM::OnDeviceStarted() {
Darin Petkovdaf43862011-10-27 11:37:28 +020079 VLOG(2) << __func__;
Darin Petkovcb547732011-11-09 13:55:26 +010080 card_proxy_.reset(
81 proxy_factory()->CreateModemGSMCardProxy(this,
Darin Petkovdaf43862011-10-27 11:37:28 +020082 cellular()->dbus_path(),
83 cellular()->dbus_owner()));
Darin Petkov184c54e2011-11-15 12:44:39 +010084 network_proxy_.reset(
85 proxy_factory()->CreateModemGSMNetworkProxy(this,
Darin Petkovdaf43862011-10-27 11:37:28 +020086 cellular()->dbus_path(),
87 cellular()->dbus_owner()));
88}
89
Darin Petkov5f316f62011-11-18 12:10:26 +010090void CellularCapabilityGSM::OnDeviceStopped() {
Darin Petkov721ac932011-11-16 15:43:09 +010091 VLOG(2) << __func__;
92 card_proxy_.reset();
93 network_proxy_.reset();
94}
95
Darin Petkov5f316f62011-11-18 12:10:26 +010096void CellularCapabilityGSM::OnServiceCreated() {
97 cellular()->service()->set_activation_state(
98 flimflam::kActivationStateActivated);
99 UpdateServingOperator();
100}
101
Darin Petkovae0c64e2011-11-15 15:50:27 +0100102void CellularCapabilityGSM::UpdateStatus(const DBusPropertiesMap &properties) {
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100103 if (ContainsKey(properties, Cellular::kPropertyIMSI)) {
104 SetHomeProvider();
Darin Petkovae0c64e2011-11-15 15:50:27 +0100105 }
106}
107
108void CellularCapabilityGSM::SetupConnectProperties(
109 DBusPropertiesMap *properties) {
110 (*properties)[Cellular::kConnectPropertyPhoneNumber].writer().append_string(
111 kPhoneNumber);
112 // TODO(petkov): Setup apn and "home_only".
113}
114
Darin Petkovcb547732011-11-09 13:55:26 +0100115void CellularCapabilityGSM::GetIdentifiers() {
116 VLOG(2) << __func__;
117 if (cellular()->imei().empty()) {
118 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
119 cellular()->set_imei(card_proxy_->GetIMEI());
Darin Petkovcb547732011-11-09 13:55:26 +0100120 }
121 if (cellular()->imsi().empty()) {
122 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Darin Petkove5bc2cb2011-12-07 14:47:32 +0100123 try {
124 cellular()->set_imsi(card_proxy_->GetIMSI());
125 VLOG(2) << "IMSI: " << cellular()->imsi();
126 } catch (const DBus::Error e) {
127 LOG(WARNING) << "Unable to obtain IMSI: " << e.what();
128 }
Darin Petkovcb547732011-11-09 13:55:26 +0100129 }
Darin Petkovae0c64e2011-11-15 15:50:27 +0100130 if (spn_.empty()) {
Darin Petkovcb547732011-11-09 13:55:26 +0100131 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
132 try {
Darin Petkovae0c64e2011-11-15 15:50:27 +0100133 spn_ = card_proxy_->GetSPN();
134 VLOG(2) << "SPN: " << spn_;
Darin Petkovcb547732011-11-09 13:55:26 +0100135 } catch (const DBus::Error e) {
136 // Some modems don't support this call so catch the exception explicitly.
137 LOG(WARNING) << "Unable to obtain SPN: " << e.what();
138 }
139 }
140 if (cellular()->mdn().empty()) {
Darin Petkovb72cf402011-11-22 14:51:39 +0100141 try {
142 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
143 cellular()->set_mdn(card_proxy_->GetMSISDN());
144 VLOG(2) << "MSISDN/MDN: " << cellular()->mdn();
145 } catch (const DBus::Error e) {
146 LOG(WARNING) << "Unable to obtain MSISDN/MDN: " << e.what();
147 }
Darin Petkovcb547732011-11-09 13:55:26 +0100148 }
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100149 SetHomeProvider();
Darin Petkovcb547732011-11-09 13:55:26 +0100150}
151
Darin Petkov3e509242011-11-10 14:46:44 +0100152void CellularCapabilityGSM::GetSignalQuality() {
153 VLOG(2) << __func__;
154 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Darin Petkov184c54e2011-11-15 12:44:39 +0100155 uint32 strength = network_proxy_->GetSignalQuality();
Darin Petkov3e509242011-11-10 14:46:44 +0100156 cellular()->HandleNewSignalQuality(strength);
157}
158
Darin Petkov184c54e2011-11-15 12:44:39 +0100159void CellularCapabilityGSM::GetRegistrationState() {
160 VLOG(2) << __func__;
161 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
162 ModemGSMNetworkProxyInterface::RegistrationInfo info =
163 network_proxy_->GetRegistrationInfo();
164 registration_state_ = info._1;
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100165 serving_operator_.SetCode(info._2);
166 serving_operator_.SetName(info._3);
Darin Petkovae0c64e2011-11-15 15:50:27 +0100167 VLOG(2) << "GSM Registration: " << registration_state_ << ", "
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100168 << serving_operator_.GetCode() << ", "
169 << serving_operator_.GetName();
Darin Petkovae0c64e2011-11-15 15:50:27 +0100170 UpdateOperatorInfo();
Darin Petkov184c54e2011-11-15 12:44:39 +0100171 cellular()->HandleNewRegistrationState();
172}
173
174void CellularCapabilityGSM::GetProperties() {
175 VLOG(2) << __func__;
176 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
177 uint32 tech = network_proxy_->AccessTechnology();
Darin Petkovae0c64e2011-11-15 15:50:27 +0100178 SetAccessTechnology(tech);
Darin Petkov184c54e2011-11-15 12:44:39 +0100179 VLOG(2) << "GSM AccessTechnology: " << tech;
180}
181
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100182void CellularCapabilityGSM::SetHomeProvider() {
183 VLOG(2) << __func__ << "(IMSI: " << cellular()->imsi()
184 << " SPN: " << spn_ << ")";
185 // TODO(petkov): The test for NULL provider_db should be done by
186 // mobile_provider_lookup_best_match.
187 if (cellular()->imsi().empty() || !cellular()->provider_db()) {
188 return;
189 }
190 mobile_provider *provider =
191 mobile_provider_lookup_best_match(
192 cellular()->provider_db(), spn_.c_str(), cellular()->imsi().c_str());
193 if (!provider) {
194 VLOG(2) << "GSM provider not found.";
195 return;
196 }
197 home_provider_ = provider;
198 Cellular::Operator oper;
199 if (provider->networks) {
200 oper.SetCode(provider->networks[0]);
201 }
202 if (provider->country) {
203 oper.SetCountry(provider->country);
204 }
205 if (spn_.empty()) {
206 const char *name = mobile_provider_get_name(provider);
207 if (name) {
208 oper.SetName(name);
209 }
210 } else {
211 oper.SetName(spn_);
212 }
213 cellular()->set_home_provider(oper);
Darin Petkov3cfbf212011-11-21 16:02:09 +0100214 InitAPNList();
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100215}
216
Darin Petkovae0c64e2011-11-15 15:50:27 +0100217void CellularCapabilityGSM::UpdateOperatorInfo() {
218 VLOG(2) << __func__;
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100219 const string &network_id = serving_operator_.GetCode();
220 if (!network_id.empty()) {
221 VLOG(2) << "Looking up network id: " << network_id;
Darin Petkovae0c64e2011-11-15 15:50:27 +0100222 mobile_provider *provider =
223 mobile_provider_lookup_by_network(cellular()->provider_db(),
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100224 network_id.c_str());
Darin Petkovae0c64e2011-11-15 15:50:27 +0100225 if (provider) {
226 const char *provider_name = mobile_provider_get_name(provider);
227 if (provider_name && *provider_name) {
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100228 serving_operator_.SetName(provider_name);
229 if (provider->country) {
230 serving_operator_.SetCountry(provider->country);
231 }
232 VLOG(2) << "Operator name: " << serving_operator_.GetName()
233 << ", country: " << serving_operator_.GetCountry();
Darin Petkovae0c64e2011-11-15 15:50:27 +0100234 }
235 } else {
236 VLOG(2) << "GSM provider not found.";
237 }
238 }
239 UpdateServingOperator();
240}
241
242void CellularCapabilityGSM::UpdateServingOperator() {
243 VLOG(2) << __func__;
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100244 if (cellular()->service().get()) {
245 cellular()->service()->set_serving_operator(serving_operator_);
Darin Petkovae0c64e2011-11-15 15:50:27 +0100246 }
Darin Petkovae0c64e2011-11-15 15:50:27 +0100247}
248
Darin Petkov3cfbf212011-11-21 16:02:09 +0100249void CellularCapabilityGSM::InitAPNList() {
250 VLOG(2) << __func__;
251 if (!home_provider_) {
252 return;
253 }
254 apn_list_.clear();
255 for (int i = 0; i < home_provider_->num_apns; ++i) {
256 Stringmap props;
257 mobile_apn *apn = home_provider_->apns[i];
258 if (apn->value) {
259 props[flimflam::kApnProperty] = apn->value;
260 }
261 if (apn->username) {
262 props[flimflam::kApnUsernameProperty] = apn->username;
263 }
264 if (apn->password) {
265 props[flimflam::kApnPasswordProperty] = apn->password;
266 }
267 // Find the first localized and non-localized name, if any.
268 const localized_name *lname = NULL;
269 const localized_name *name = NULL;
270 for (int j = 0; j < apn->num_names; ++j) {
271 if (apn->names[j]->lang) {
272 if (!lname) {
273 lname = apn->names[j];
274 }
275 } else if (!name) {
276 name = apn->names[j];
277 }
278 }
279 if (name) {
280 props[flimflam::kApnNameProperty] = name->name;
281 }
282 if (lname) {
283 props[flimflam::kApnLocalizedNameProperty] = lname->name;
284 props[flimflam::kApnLanguageProperty] = lname->lang;
285 }
286 apn_list_.push_back(props);
287 }
288 cellular()->adaptor()->EmitStringmapsChanged(
289 flimflam::kCellularApnListProperty, apn_list_);
290}
291
Darin Petkov184c54e2011-11-15 12:44:39 +0100292void CellularCapabilityGSM::Register() {
293 LOG(INFO) << __func__ << " \"" << selected_network_ << "\"";
294 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
295 network_proxy_->Register(selected_network_);
296 // TODO(petkov): Handle registration failure including trying the home network
297 // when selected_network_ is not empty.
298}
299
300void CellularCapabilityGSM::RegisterOnNetwork(
301 const string &network_id, Error */*error*/) {
302 LOG(INFO) << __func__ << "(" << network_id << ")";
303 // Defer because we may be in a dbus-c++ callback.
304 dispatcher()->PostTask(
305 task_factory_.NewRunnableMethod(
306 &CellularCapabilityGSM::RegisterOnNetworkTask,
307 network_id));
308}
309
Darin Petkovb72cf402011-11-22 14:51:39 +0100310bool CellularCapabilityGSM::IsRegistered() {
311 return (registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME ||
312 registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING);
313}
314
Darin Petkov184c54e2011-11-15 12:44:39 +0100315void CellularCapabilityGSM::RegisterOnNetworkTask(const string &network_id) {
316 LOG(INFO) << __func__ << "(" << network_id << ")";
317 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
318 network_proxy_->Register(network_id);
319 // TODO(petkov): Handle registration failure.
320 selected_network_ = network_id;
321}
322
Darin Petkovb05315f2011-11-07 10:14:25 +0100323void CellularCapabilityGSM::RequirePIN(
324 const string &pin, bool require, Error */*error*/) {
325 VLOG(2) << __func__ << "(" << pin << ", " << require << ")";
326 // Defer because we may be in a dbus-c++ callback.
327 dispatcher()->PostTask(
328 task_factory_.NewRunnableMethod(
329 &CellularCapabilityGSM::RequirePINTask, pin, require));
330}
331
332void CellularCapabilityGSM::RequirePINTask(const string &pin, bool require) {
333 VLOG(2) << __func__ << "(" << pin << ", " << require << ")";
334 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Darin Petkovcb547732011-11-09 13:55:26 +0100335 card_proxy_->EnablePIN(pin, require);
Darin Petkovb05315f2011-11-07 10:14:25 +0100336}
337
Darin Petkove5bc2cb2011-12-07 14:47:32 +0100338void CellularCapabilityGSM::EnterPIN(const string &pin,
339 ReturnerInterface *returner) {
340 VLOG(2) << __func__ << "(" << returner << ")";
Darin Petkovb05315f2011-11-07 10:14:25 +0100341 // Defer because we may be in a dbus-c++ callback.
342 dispatcher()->PostTask(
343 task_factory_.NewRunnableMethod(
Darin Petkove5bc2cb2011-12-07 14:47:32 +0100344 &CellularCapabilityGSM::EnterPINTask, pin, returner));
Darin Petkovb05315f2011-11-07 10:14:25 +0100345}
346
Darin Petkove5bc2cb2011-12-07 14:47:32 +0100347void CellularCapabilityGSM::EnterPINTask(const string &pin,
348 ReturnerInterface *returner) {
349 VLOG(2) << __func__ << "(" << returner << ")";
Darin Petkovb05315f2011-11-07 10:14:25 +0100350 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Darin Petkove5bc2cb2011-12-07 14:47:32 +0100351 try {
352 card_proxy_->SendPIN(pin);
353 } catch (DBus::Error e) {
354 LOG(ERROR) << "EnterPIN failed: " << e.name() << "/" << e.message();
355 returner->ReturnError(Error(Error::kInternalError));
356 return;
357 }
358 returner->Return();
Darin Petkovb05315f2011-11-07 10:14:25 +0100359}
360
361void CellularCapabilityGSM::UnblockPIN(
362 const string &unblock_code, const string &pin, Error */*error*/) {
363 VLOG(2) << __func__ << "(" << unblock_code << ", " << pin << ")";
364 // Defer because we may be in a dbus-c++ callback.
365 dispatcher()->PostTask(
366 task_factory_.NewRunnableMethod(
367 &CellularCapabilityGSM::UnblockPINTask, unblock_code, pin));
368}
369
370void CellularCapabilityGSM::UnblockPINTask(
371 const string &unblock_code, const string &pin) {
372 VLOG(2) << __func__ << "(" << unblock_code << ", " << pin << ")";
373 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Darin Petkovcb547732011-11-09 13:55:26 +0100374 card_proxy_->SendPUK(unblock_code, pin);
Darin Petkovb05315f2011-11-07 10:14:25 +0100375}
376
377void CellularCapabilityGSM::ChangePIN(
378 const string &old_pin, const string &new_pin, Error */*error*/) {
379 VLOG(2) << __func__ << "(" << old_pin << ", " << new_pin << ")";
380 // Defer because we may be in a dbus-c++ callback.
381 dispatcher()->PostTask(
382 task_factory_.NewRunnableMethod(
383 &CellularCapabilityGSM::ChangePINTask, old_pin, new_pin));
384}
385
386void CellularCapabilityGSM::ChangePINTask(
387 const string &old_pin, const string &new_pin) {
388 VLOG(2) << __func__ << "(" << old_pin << ", " << new_pin << ")";
389 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Darin Petkovcb547732011-11-09 13:55:26 +0100390 card_proxy_->ChangePIN(old_pin, new_pin);
Darin Petkovb05315f2011-11-07 10:14:25 +0100391}
392
Darin Petkov1272a432011-11-10 15:53:37 +0100393void CellularCapabilityGSM::Scan(Error */*error*/) {
394 VLOG(2) << __func__;
395 // Defer because we may be in a dbus-c++ callback.
396 dispatcher()->PostTask(
397 task_factory_.NewRunnableMethod(&CellularCapabilityGSM::ScanTask));
398}
399
400void CellularCapabilityGSM::ScanTask() {
401 VLOG(2) << __func__;
402 // TODO(petkov): Defer scan requests if a scan is in progress already.
403 //
404 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583). This is a
405 // must for this call which is basically a stub at this point.
Darin Petkov184c54e2011-11-15 12:44:39 +0100406 ModemGSMNetworkProxyInterface::ScanResults results = network_proxy_->Scan();
Darin Petkov1272a432011-11-10 15:53:37 +0100407 found_networks_.clear();
408 for (ModemGSMNetworkProxyInterface::ScanResults::const_iterator it =
409 results.begin(); it != results.end(); ++it) {
410 found_networks_.push_back(ParseScanResult(*it));
411 }
412}
413
414Stringmap CellularCapabilityGSM::ParseScanResult(
415 const ModemGSMNetworkProxyInterface::ScanResult &result) {
416 Stringmap parsed;
417 for (ModemGSMNetworkProxyInterface::ScanResult::const_iterator it =
418 result.begin(); it != result.end(); ++it) {
419 // TODO(petkov): Define these in system_api/service_constants.h. The
420 // numerical values are taken from 3GPP TS 27.007 Section 7.3.
421 static const char * const kStatusString[] = {
422 "unknown",
423 "available",
424 "current",
425 "forbidden",
426 };
427 static const char * const kTechnologyString[] = {
428 flimflam::kNetworkTechnologyGsm,
429 "GSM Compact",
430 flimflam::kNetworkTechnologyUmts,
431 flimflam::kNetworkTechnologyEdge,
432 "HSDPA",
433 "HSUPA",
434 flimflam::kNetworkTechnologyHspa,
435 };
436 VLOG(2) << "Network property: " << it->first << " = " << it->second;
437 if (it->first == kNetworkPropertyStatus) {
438 int status = 0;
439 if (base::StringToInt(it->second, &status) &&
440 status >= 0 &&
441 status < static_cast<int>(arraysize(kStatusString))) {
442 parsed[flimflam::kStatusProperty] = kStatusString[status];
443 } else {
444 LOG(ERROR) << "Unexpected status value: " << it->second;
445 }
446 } else if (it->first == kNetworkPropertyID) {
447 parsed[flimflam::kNetworkIdProperty] = it->second;
448 } else if (it->first == kNetworkPropertyLongName) {
449 parsed[flimflam::kLongNameProperty] = it->second;
450 } else if (it->first == kNetworkPropertyShortName) {
451 parsed[flimflam::kShortNameProperty] = it->second;
452 } else if (it->first == kNetworkPropertyAccessTechnology) {
453 int tech = 0;
454 if (base::StringToInt(it->second, &tech) &&
455 tech >= 0 &&
456 tech < static_cast<int>(arraysize(kTechnologyString))) {
457 parsed[flimflam::kTechnologyProperty] = kTechnologyString[tech];
458 } else {
459 LOG(ERROR) << "Unexpected technology value: " << it->second;
460 }
461 } else {
462 LOG(WARNING) << "Unknown network property ignored: " << it->first;
463 }
464 }
465 // If the long name is not available but the network ID is, look up the long
466 // name in the mobile provider database.
467 if ((!ContainsKey(parsed, flimflam::kLongNameProperty) ||
468 parsed[flimflam::kLongNameProperty].empty()) &&
469 ContainsKey(parsed, flimflam::kNetworkIdProperty)) {
470 mobile_provider *provider =
471 mobile_provider_lookup_by_network(
472 cellular()->provider_db(),
473 parsed[flimflam::kNetworkIdProperty].c_str());
474 if (provider) {
475 const char *long_name = mobile_provider_get_name(provider);
476 if (long_name && *long_name) {
477 parsed[flimflam::kLongNameProperty] = long_name;
478 }
479 }
480 }
481 return parsed;
482}
483
Darin Petkovae0c64e2011-11-15 15:50:27 +0100484void CellularCapabilityGSM::SetAccessTechnology(uint32 access_technology) {
485 access_technology_ = access_technology;
486 if (cellular()->service().get()) {
Darin Petkovb72cf402011-11-22 14:51:39 +0100487 cellular()->service()->SetNetworkTechnology(GetNetworkTechnologyString());
Darin Petkovae0c64e2011-11-15 15:50:27 +0100488 }
489}
490
Darin Petkov20c13ec2011-11-09 15:07:15 +0100491string CellularCapabilityGSM::GetNetworkTechnologyString() const {
Darin Petkovb72cf402011-11-22 14:51:39 +0100492 switch (access_technology_) {
493 case MM_MODEM_GSM_ACCESS_TECH_GSM:
494 case MM_MODEM_GSM_ACCESS_TECH_GSM_COMPACT:
495 return flimflam::kNetworkTechnologyGsm;
496 case MM_MODEM_GSM_ACCESS_TECH_GPRS:
497 return flimflam::kNetworkTechnologyGprs;
498 case MM_MODEM_GSM_ACCESS_TECH_EDGE:
499 return flimflam::kNetworkTechnologyEdge;
500 case MM_MODEM_GSM_ACCESS_TECH_UMTS:
501 return flimflam::kNetworkTechnologyUmts;
502 case MM_MODEM_GSM_ACCESS_TECH_HSDPA:
503 case MM_MODEM_GSM_ACCESS_TECH_HSUPA:
504 case MM_MODEM_GSM_ACCESS_TECH_HSPA:
505 return flimflam::kNetworkTechnologyHspa;
506 case MM_MODEM_GSM_ACCESS_TECH_HSPA_PLUS:
507 return flimflam::kNetworkTechnologyHspaPlus;
508 default:
509 break;
Darin Petkov20c13ec2011-11-09 15:07:15 +0100510 }
511 return "";
512}
513
514string CellularCapabilityGSM::GetRoamingStateString() const {
Darin Petkov184c54e2011-11-15 12:44:39 +0100515 switch (registration_state_) {
Darin Petkov20c13ec2011-11-09 15:07:15 +0100516 case MM_MODEM_GSM_NETWORK_REG_STATUS_HOME:
517 return flimflam::kRoamingStateHome;
518 case MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING:
519 return flimflam::kRoamingStateRoaming;
520 default:
521 break;
522 }
523 return flimflam::kRoamingStateUnknown;
524}
525
Darin Petkovae0c64e2011-11-15 15:50:27 +0100526void CellularCapabilityGSM::OnModemManagerPropertiesChanged(
527 const DBusPropertiesMap &properties) {
528 uint32 access_technology = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN;
529 if (DBusProperties::GetUint32(properties,
530 kPropertyAccessTechnology,
531 &access_technology)) {
532 SetAccessTechnology(access_technology);
533 }
Darin Petkov721ac932011-11-16 15:43:09 +0100534 DBusProperties::GetString(
535 properties, kPropertyUnlockRequired, &sim_lock_status_.lock_type);
536 DBusProperties::GetUint32(
537 properties, kPropertyUnlockRetries, &sim_lock_status_.retries_left);
Darin Petkovae0c64e2011-11-15 15:50:27 +0100538}
539
Darin Petkov184c54e2011-11-15 12:44:39 +0100540void CellularCapabilityGSM::OnGSMNetworkModeChanged(uint32 /*mode*/) {
541 // TODO(petkov): Implement this.
542 NOTIMPLEMENTED();
543}
544
545void CellularCapabilityGSM::OnGSMRegistrationInfoChanged(
546 uint32 status, const string &operator_code, const string &operator_name) {
547 registration_state_ = status;
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100548 serving_operator_.SetCode(operator_code);
549 serving_operator_.SetName(operator_name);
Darin Petkovae0c64e2011-11-15 15:50:27 +0100550 UpdateOperatorInfo();
Darin Petkov184c54e2011-11-15 12:44:39 +0100551 cellular()->HandleNewRegistrationState();
552}
553
554void CellularCapabilityGSM::OnGSMSignalQualityChanged(uint32 quality) {
555 cellular()->HandleNewSignalQuality(quality);
556}
557
Darin Petkovdaf43862011-10-27 11:37:28 +0200558} // namespace shill