blob: 842e30f546940e4802f7e163a361f50cb727fd2e [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 Petkovae0c64e2011-11-15 15:50:27 +010014#include "shill/cellular_service.h"
Darin Petkov721ac932011-11-16 15:43:09 +010015#include "shill/property_accessor.h"
Darin Petkovdaf43862011-10-27 11:37:28 +020016#include "shill/proxy_factory.h"
17
Darin Petkov721ac932011-11-16 15:43:09 +010018using std::make_pair;
Darin Petkovb05315f2011-11-07 10:14:25 +010019using std::string;
20
Darin Petkovdaf43862011-10-27 11:37:28 +020021namespace shill {
22
Darin Petkov1272a432011-11-10 15:53:37 +010023const char CellularCapabilityGSM::kNetworkPropertyAccessTechnology[] =
24 "access-tech";
25const char CellularCapabilityGSM::kNetworkPropertyID[] = "operator-num";
26const char CellularCapabilityGSM::kNetworkPropertyLongName[] = "operator-long";
27const char CellularCapabilityGSM::kNetworkPropertyShortName[] =
28 "operator-short";
29const char CellularCapabilityGSM::kNetworkPropertyStatus[] = "status";
Darin Petkovae0c64e2011-11-15 15:50:27 +010030const char CellularCapabilityGSM::kPhoneNumber[] = "*99#";
31const char CellularCapabilityGSM::kPropertyAccessTechnology[] =
32 "AccessTechnology";
Darin Petkov721ac932011-11-16 15:43:09 +010033const char CellularCapabilityGSM::kPropertyUnlockRequired[] = "UnlockRequired";
34const char CellularCapabilityGSM::kPropertyUnlockRetries[] = "UnlockRetries";
Darin Petkov1272a432011-11-10 15:53:37 +010035
Darin Petkovdaf43862011-10-27 11:37:28 +020036CellularCapabilityGSM::CellularCapabilityGSM(Cellular *cellular)
Darin Petkovb05315f2011-11-07 10:14:25 +010037 : CellularCapability(cellular),
Darin Petkov1272a432011-11-10 15:53:37 +010038 task_factory_(this),
Darin Petkov184c54e2011-11-15 12:44:39 +010039 registration_state_(MM_MODEM_GSM_NETWORK_REG_STATUS_UNKNOWN),
Darin Petkovae0c64e2011-11-15 15:50:27 +010040 access_technology_(MM_MODEM_GSM_ACCESS_TECH_UNKNOWN),
Darin Petkov0a4dfeb2011-11-18 19:36:13 +010041 home_provider_(NULL),
Darin Petkov1272a432011-11-10 15:53:37 +010042 scanning_(false),
43 scan_interval_(0) {
Darin Petkov5f316f62011-11-18 12:10:26 +010044 VLOG(2) << "Cellular capability constructed: GSM";
Darin Petkov1272a432011-11-10 15:53:37 +010045 PropertyStore *store = cellular->mutable_store();
Darin Petkov184c54e2011-11-15 12:44:39 +010046 store->RegisterConstString(flimflam::kSelectedNetworkProperty,
47 &selected_network_);
Darin Petkov1272a432011-11-10 15:53:37 +010048 store->RegisterConstStringmaps(flimflam::kFoundNetworksProperty,
49 &found_networks_);
50 store->RegisterConstBool(flimflam::kScanningProperty, &scanning_);
51 store->RegisterUint16(flimflam::kScanIntervalProperty, &scan_interval_);
Darin Petkov721ac932011-11-16 15:43:09 +010052 HelpRegisterDerivedStrIntPair(flimflam::kSIMLockStatusProperty,
53 &CellularCapabilityGSM::SimLockStatusToProperty,
54 NULL);
Darin Petkov1272a432011-11-10 15:53:37 +010055}
Darin Petkovdaf43862011-10-27 11:37:28 +020056
Darin Petkov721ac932011-11-16 15:43:09 +010057StrIntPair CellularCapabilityGSM::SimLockStatusToProperty(Error */*error*/) {
58 return StrIntPair(make_pair(flimflam::kSIMLockTypeProperty,
59 sim_lock_status_.lock_type),
60 make_pair(flimflam::kSIMLockRetriesLeftProperty,
61 sim_lock_status_.retries_left));
62}
63
64void CellularCapabilityGSM::HelpRegisterDerivedStrIntPair(
65 const string &name,
66 StrIntPair(CellularCapabilityGSM::*get)(Error *),
67 void(CellularCapabilityGSM::*set)(const StrIntPair &, Error *)) {
68 cellular()->mutable_store()->RegisterDerivedStrIntPair(
69 name,
70 StrIntPairAccessor(
71 new CustomAccessor<CellularCapabilityGSM, StrIntPair>(
72 this, get, set)));
73}
74
Darin Petkov5f316f62011-11-18 12:10:26 +010075void CellularCapabilityGSM::OnDeviceStarted() {
Darin Petkovdaf43862011-10-27 11:37:28 +020076 VLOG(2) << __func__;
Darin Petkovcb547732011-11-09 13:55:26 +010077 card_proxy_.reset(
78 proxy_factory()->CreateModemGSMCardProxy(this,
Darin Petkovdaf43862011-10-27 11:37:28 +020079 cellular()->dbus_path(),
80 cellular()->dbus_owner()));
Darin Petkov184c54e2011-11-15 12:44:39 +010081 network_proxy_.reset(
82 proxy_factory()->CreateModemGSMNetworkProxy(this,
Darin Petkovdaf43862011-10-27 11:37:28 +020083 cellular()->dbus_path(),
84 cellular()->dbus_owner()));
85}
86
Darin Petkov5f316f62011-11-18 12:10:26 +010087void CellularCapabilityGSM::OnDeviceStopped() {
Darin Petkov721ac932011-11-16 15:43:09 +010088 VLOG(2) << __func__;
89 card_proxy_.reset();
90 network_proxy_.reset();
91}
92
Darin Petkov5f316f62011-11-18 12:10:26 +010093void CellularCapabilityGSM::OnServiceCreated() {
94 cellular()->service()->set_activation_state(
95 flimflam::kActivationStateActivated);
96 UpdateServingOperator();
97}
98
Darin Petkovae0c64e2011-11-15 15:50:27 +010099void CellularCapabilityGSM::UpdateStatus(const DBusPropertiesMap &properties) {
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100100 if (ContainsKey(properties, Cellular::kPropertyIMSI)) {
101 SetHomeProvider();
Darin Petkovae0c64e2011-11-15 15:50:27 +0100102 }
103}
104
105void CellularCapabilityGSM::SetupConnectProperties(
106 DBusPropertiesMap *properties) {
107 (*properties)[Cellular::kConnectPropertyPhoneNumber].writer().append_string(
108 kPhoneNumber);
109 // TODO(petkov): Setup apn and "home_only".
110}
111
Darin Petkovcb547732011-11-09 13:55:26 +0100112void CellularCapabilityGSM::GetIdentifiers() {
113 VLOG(2) << __func__;
114 if (cellular()->imei().empty()) {
115 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
116 cellular()->set_imei(card_proxy_->GetIMEI());
117 VLOG(2) << "IMEI: " << cellular()->imei();
118 }
119 if (cellular()->imsi().empty()) {
120 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
121 cellular()->set_imsi(card_proxy_->GetIMSI());
122 VLOG(2) << "IMSI: " << cellular()->imsi();
123 }
Darin Petkovae0c64e2011-11-15 15:50:27 +0100124 if (spn_.empty()) {
Darin Petkovcb547732011-11-09 13:55:26 +0100125 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
126 try {
Darin Petkovae0c64e2011-11-15 15:50:27 +0100127 spn_ = card_proxy_->GetSPN();
128 VLOG(2) << "SPN: " << spn_;
Darin Petkovcb547732011-11-09 13:55:26 +0100129 } catch (const DBus::Error e) {
130 // Some modems don't support this call so catch the exception explicitly.
131 LOG(WARNING) << "Unable to obtain SPN: " << e.what();
132 }
133 }
134 if (cellular()->mdn().empty()) {
135 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
136 cellular()->set_mdn(card_proxy_->GetMSISDN());
137 VLOG(2) << "MSISDN/MDN: " << cellular()->mdn();
138 }
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100139 SetHomeProvider();
Darin Petkovcb547732011-11-09 13:55:26 +0100140}
141
Darin Petkov3e509242011-11-10 14:46:44 +0100142void CellularCapabilityGSM::GetSignalQuality() {
143 VLOG(2) << __func__;
144 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Darin Petkov184c54e2011-11-15 12:44:39 +0100145 uint32 strength = network_proxy_->GetSignalQuality();
Darin Petkov3e509242011-11-10 14:46:44 +0100146 cellular()->HandleNewSignalQuality(strength);
147}
148
Darin Petkov184c54e2011-11-15 12:44:39 +0100149void CellularCapabilityGSM::GetRegistrationState() {
150 VLOG(2) << __func__;
151 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
152 ModemGSMNetworkProxyInterface::RegistrationInfo info =
153 network_proxy_->GetRegistrationInfo();
154 registration_state_ = info._1;
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100155 serving_operator_.SetCode(info._2);
156 serving_operator_.SetName(info._3);
Darin Petkovae0c64e2011-11-15 15:50:27 +0100157 VLOG(2) << "GSM Registration: " << registration_state_ << ", "
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100158 << serving_operator_.GetCode() << ", "
159 << serving_operator_.GetName();
Darin Petkovae0c64e2011-11-15 15:50:27 +0100160 UpdateOperatorInfo();
Darin Petkov184c54e2011-11-15 12:44:39 +0100161 cellular()->HandleNewRegistrationState();
162}
163
164void CellularCapabilityGSM::GetProperties() {
165 VLOG(2) << __func__;
166 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
167 uint32 tech = network_proxy_->AccessTechnology();
Darin Petkovae0c64e2011-11-15 15:50:27 +0100168 SetAccessTechnology(tech);
Darin Petkov184c54e2011-11-15 12:44:39 +0100169 VLOG(2) << "GSM AccessTechnology: " << tech;
170}
171
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100172void CellularCapabilityGSM::SetHomeProvider() {
173 VLOG(2) << __func__ << "(IMSI: " << cellular()->imsi()
174 << " SPN: " << spn_ << ")";
175 // TODO(petkov): The test for NULL provider_db should be done by
176 // mobile_provider_lookup_best_match.
177 if (cellular()->imsi().empty() || !cellular()->provider_db()) {
178 return;
179 }
180 mobile_provider *provider =
181 mobile_provider_lookup_best_match(
182 cellular()->provider_db(), spn_.c_str(), cellular()->imsi().c_str());
183 if (!provider) {
184 VLOG(2) << "GSM provider not found.";
185 return;
186 }
187 home_provider_ = provider;
188 Cellular::Operator oper;
189 if (provider->networks) {
190 oper.SetCode(provider->networks[0]);
191 }
192 if (provider->country) {
193 oper.SetCountry(provider->country);
194 }
195 if (spn_.empty()) {
196 const char *name = mobile_provider_get_name(provider);
197 if (name) {
198 oper.SetName(name);
199 }
200 } else {
201 oper.SetName(spn_);
202 }
203 cellular()->set_home_provider(oper);
204 // TODO(petkov): Create APN list (crosbug.com/23201).
205}
206
Darin Petkovae0c64e2011-11-15 15:50:27 +0100207void CellularCapabilityGSM::UpdateOperatorInfo() {
208 VLOG(2) << __func__;
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100209 const string &network_id = serving_operator_.GetCode();
210 if (!network_id.empty()) {
211 VLOG(2) << "Looking up network id: " << network_id;
Darin Petkovae0c64e2011-11-15 15:50:27 +0100212 mobile_provider *provider =
213 mobile_provider_lookup_by_network(cellular()->provider_db(),
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100214 network_id.c_str());
Darin Petkovae0c64e2011-11-15 15:50:27 +0100215 if (provider) {
216 const char *provider_name = mobile_provider_get_name(provider);
217 if (provider_name && *provider_name) {
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100218 serving_operator_.SetName(provider_name);
219 if (provider->country) {
220 serving_operator_.SetCountry(provider->country);
221 }
222 VLOG(2) << "Operator name: " << serving_operator_.GetName()
223 << ", country: " << serving_operator_.GetCountry();
Darin Petkovae0c64e2011-11-15 15:50:27 +0100224 }
225 } else {
226 VLOG(2) << "GSM provider not found.";
227 }
228 }
229 UpdateServingOperator();
230}
231
232void CellularCapabilityGSM::UpdateServingOperator() {
233 VLOG(2) << __func__;
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100234 if (cellular()->service().get()) {
235 cellular()->service()->set_serving_operator(serving_operator_);
Darin Petkovae0c64e2011-11-15 15:50:27 +0100236 }
Darin Petkovae0c64e2011-11-15 15:50:27 +0100237}
238
Darin Petkov184c54e2011-11-15 12:44:39 +0100239void CellularCapabilityGSM::Register() {
240 LOG(INFO) << __func__ << " \"" << selected_network_ << "\"";
241 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
242 network_proxy_->Register(selected_network_);
243 // TODO(petkov): Handle registration failure including trying the home network
244 // when selected_network_ is not empty.
245}
246
247void CellularCapabilityGSM::RegisterOnNetwork(
248 const string &network_id, Error */*error*/) {
249 LOG(INFO) << __func__ << "(" << network_id << ")";
250 // Defer because we may be in a dbus-c++ callback.
251 dispatcher()->PostTask(
252 task_factory_.NewRunnableMethod(
253 &CellularCapabilityGSM::RegisterOnNetworkTask,
254 network_id));
255}
256
257void CellularCapabilityGSM::RegisterOnNetworkTask(const string &network_id) {
258 LOG(INFO) << __func__ << "(" << network_id << ")";
259 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
260 network_proxy_->Register(network_id);
261 // TODO(petkov): Handle registration failure.
262 selected_network_ = network_id;
263}
264
Darin Petkovb05315f2011-11-07 10:14:25 +0100265void CellularCapabilityGSM::RequirePIN(
266 const string &pin, bool require, Error */*error*/) {
267 VLOG(2) << __func__ << "(" << pin << ", " << require << ")";
268 // Defer because we may be in a dbus-c++ callback.
269 dispatcher()->PostTask(
270 task_factory_.NewRunnableMethod(
271 &CellularCapabilityGSM::RequirePINTask, pin, require));
272}
273
274void CellularCapabilityGSM::RequirePINTask(const string &pin, bool require) {
275 VLOG(2) << __func__ << "(" << pin << ", " << require << ")";
276 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Darin Petkovcb547732011-11-09 13:55:26 +0100277 card_proxy_->EnablePIN(pin, require);
Darin Petkovb05315f2011-11-07 10:14:25 +0100278}
279
280void CellularCapabilityGSM::EnterPIN(const string &pin, Error */*error*/) {
281 VLOG(2) << __func__ << "(" << pin << ")";
282 // Defer because we may be in a dbus-c++ callback.
283 dispatcher()->PostTask(
284 task_factory_.NewRunnableMethod(
285 &CellularCapabilityGSM::EnterPINTask, pin));
286}
287
288void CellularCapabilityGSM::EnterPINTask(const string &pin) {
289 VLOG(2) << __func__ << "(" << pin << ")";
290 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Darin Petkovcb547732011-11-09 13:55:26 +0100291 card_proxy_->SendPIN(pin);
Darin Petkovb05315f2011-11-07 10:14:25 +0100292}
293
294void CellularCapabilityGSM::UnblockPIN(
295 const string &unblock_code, const string &pin, Error */*error*/) {
296 VLOG(2) << __func__ << "(" << unblock_code << ", " << pin << ")";
297 // Defer because we may be in a dbus-c++ callback.
298 dispatcher()->PostTask(
299 task_factory_.NewRunnableMethod(
300 &CellularCapabilityGSM::UnblockPINTask, unblock_code, pin));
301}
302
303void CellularCapabilityGSM::UnblockPINTask(
304 const string &unblock_code, const string &pin) {
305 VLOG(2) << __func__ << "(" << unblock_code << ", " << pin << ")";
306 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Darin Petkovcb547732011-11-09 13:55:26 +0100307 card_proxy_->SendPUK(unblock_code, pin);
Darin Petkovb05315f2011-11-07 10:14:25 +0100308}
309
310void CellularCapabilityGSM::ChangePIN(
311 const string &old_pin, const string &new_pin, Error */*error*/) {
312 VLOG(2) << __func__ << "(" << old_pin << ", " << new_pin << ")";
313 // Defer because we may be in a dbus-c++ callback.
314 dispatcher()->PostTask(
315 task_factory_.NewRunnableMethod(
316 &CellularCapabilityGSM::ChangePINTask, old_pin, new_pin));
317}
318
319void CellularCapabilityGSM::ChangePINTask(
320 const string &old_pin, const string &new_pin) {
321 VLOG(2) << __func__ << "(" << old_pin << ", " << new_pin << ")";
322 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Darin Petkovcb547732011-11-09 13:55:26 +0100323 card_proxy_->ChangePIN(old_pin, new_pin);
Darin Petkovb05315f2011-11-07 10:14:25 +0100324}
325
Darin Petkov1272a432011-11-10 15:53:37 +0100326void CellularCapabilityGSM::Scan(Error */*error*/) {
327 VLOG(2) << __func__;
328 // Defer because we may be in a dbus-c++ callback.
329 dispatcher()->PostTask(
330 task_factory_.NewRunnableMethod(&CellularCapabilityGSM::ScanTask));
331}
332
333void CellularCapabilityGSM::ScanTask() {
334 VLOG(2) << __func__;
335 // TODO(petkov): Defer scan requests if a scan is in progress already.
336 //
337 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583). This is a
338 // must for this call which is basically a stub at this point.
Darin Petkov184c54e2011-11-15 12:44:39 +0100339 ModemGSMNetworkProxyInterface::ScanResults results = network_proxy_->Scan();
Darin Petkov1272a432011-11-10 15:53:37 +0100340 found_networks_.clear();
341 for (ModemGSMNetworkProxyInterface::ScanResults::const_iterator it =
342 results.begin(); it != results.end(); ++it) {
343 found_networks_.push_back(ParseScanResult(*it));
344 }
345}
346
347Stringmap CellularCapabilityGSM::ParseScanResult(
348 const ModemGSMNetworkProxyInterface::ScanResult &result) {
349 Stringmap parsed;
350 for (ModemGSMNetworkProxyInterface::ScanResult::const_iterator it =
351 result.begin(); it != result.end(); ++it) {
352 // TODO(petkov): Define these in system_api/service_constants.h. The
353 // numerical values are taken from 3GPP TS 27.007 Section 7.3.
354 static const char * const kStatusString[] = {
355 "unknown",
356 "available",
357 "current",
358 "forbidden",
359 };
360 static const char * const kTechnologyString[] = {
361 flimflam::kNetworkTechnologyGsm,
362 "GSM Compact",
363 flimflam::kNetworkTechnologyUmts,
364 flimflam::kNetworkTechnologyEdge,
365 "HSDPA",
366 "HSUPA",
367 flimflam::kNetworkTechnologyHspa,
368 };
369 VLOG(2) << "Network property: " << it->first << " = " << it->second;
370 if (it->first == kNetworkPropertyStatus) {
371 int status = 0;
372 if (base::StringToInt(it->second, &status) &&
373 status >= 0 &&
374 status < static_cast<int>(arraysize(kStatusString))) {
375 parsed[flimflam::kStatusProperty] = kStatusString[status];
376 } else {
377 LOG(ERROR) << "Unexpected status value: " << it->second;
378 }
379 } else if (it->first == kNetworkPropertyID) {
380 parsed[flimflam::kNetworkIdProperty] = it->second;
381 } else if (it->first == kNetworkPropertyLongName) {
382 parsed[flimflam::kLongNameProperty] = it->second;
383 } else if (it->first == kNetworkPropertyShortName) {
384 parsed[flimflam::kShortNameProperty] = it->second;
385 } else if (it->first == kNetworkPropertyAccessTechnology) {
386 int tech = 0;
387 if (base::StringToInt(it->second, &tech) &&
388 tech >= 0 &&
389 tech < static_cast<int>(arraysize(kTechnologyString))) {
390 parsed[flimflam::kTechnologyProperty] = kTechnologyString[tech];
391 } else {
392 LOG(ERROR) << "Unexpected technology value: " << it->second;
393 }
394 } else {
395 LOG(WARNING) << "Unknown network property ignored: " << it->first;
396 }
397 }
398 // If the long name is not available but the network ID is, look up the long
399 // name in the mobile provider database.
400 if ((!ContainsKey(parsed, flimflam::kLongNameProperty) ||
401 parsed[flimflam::kLongNameProperty].empty()) &&
402 ContainsKey(parsed, flimflam::kNetworkIdProperty)) {
403 mobile_provider *provider =
404 mobile_provider_lookup_by_network(
405 cellular()->provider_db(),
406 parsed[flimflam::kNetworkIdProperty].c_str());
407 if (provider) {
408 const char *long_name = mobile_provider_get_name(provider);
409 if (long_name && *long_name) {
410 parsed[flimflam::kLongNameProperty] = long_name;
411 }
412 }
413 }
414 return parsed;
415}
416
Darin Petkovae0c64e2011-11-15 15:50:27 +0100417void CellularCapabilityGSM::SetAccessTechnology(uint32 access_technology) {
418 access_technology_ = access_technology;
419 if (cellular()->service().get()) {
420 cellular()->service()->set_network_tech(GetNetworkTechnologyString());
421 }
422}
423
Darin Petkov20c13ec2011-11-09 15:07:15 +0100424string CellularCapabilityGSM::GetNetworkTechnologyString() const {
Darin Petkov184c54e2011-11-15 12:44:39 +0100425 if (registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME ||
426 registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING) {
Darin Petkovae0c64e2011-11-15 15:50:27 +0100427 switch (access_technology_) {
Darin Petkov20c13ec2011-11-09 15:07:15 +0100428 case MM_MODEM_GSM_ACCESS_TECH_GSM:
429 case MM_MODEM_GSM_ACCESS_TECH_GSM_COMPACT:
430 return flimflam::kNetworkTechnologyGsm;
431 case MM_MODEM_GSM_ACCESS_TECH_GPRS:
432 return flimflam::kNetworkTechnologyGprs;
433 case MM_MODEM_GSM_ACCESS_TECH_EDGE:
434 return flimflam::kNetworkTechnologyEdge;
435 case MM_MODEM_GSM_ACCESS_TECH_UMTS:
436 return flimflam::kNetworkTechnologyUmts;
437 case MM_MODEM_GSM_ACCESS_TECH_HSDPA:
438 case MM_MODEM_GSM_ACCESS_TECH_HSUPA:
439 case MM_MODEM_GSM_ACCESS_TECH_HSPA:
440 return flimflam::kNetworkTechnologyHspa;
441 case MM_MODEM_GSM_ACCESS_TECH_HSPA_PLUS:
442 return flimflam::kNetworkTechnologyHspaPlus;
443 default:
444 NOTREACHED();
445 }
446 }
447 return "";
448}
449
450string CellularCapabilityGSM::GetRoamingStateString() const {
Darin Petkov184c54e2011-11-15 12:44:39 +0100451 switch (registration_state_) {
Darin Petkov20c13ec2011-11-09 15:07:15 +0100452 case MM_MODEM_GSM_NETWORK_REG_STATUS_HOME:
453 return flimflam::kRoamingStateHome;
454 case MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING:
455 return flimflam::kRoamingStateRoaming;
456 default:
457 break;
458 }
459 return flimflam::kRoamingStateUnknown;
460}
461
Darin Petkovae0c64e2011-11-15 15:50:27 +0100462void CellularCapabilityGSM::OnModemManagerPropertiesChanged(
463 const DBusPropertiesMap &properties) {
464 uint32 access_technology = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN;
465 if (DBusProperties::GetUint32(properties,
466 kPropertyAccessTechnology,
467 &access_technology)) {
468 SetAccessTechnology(access_technology);
469 }
Darin Petkov721ac932011-11-16 15:43:09 +0100470 DBusProperties::GetString(
471 properties, kPropertyUnlockRequired, &sim_lock_status_.lock_type);
472 DBusProperties::GetUint32(
473 properties, kPropertyUnlockRetries, &sim_lock_status_.retries_left);
Darin Petkovae0c64e2011-11-15 15:50:27 +0100474}
475
Darin Petkov184c54e2011-11-15 12:44:39 +0100476void CellularCapabilityGSM::OnGSMNetworkModeChanged(uint32 /*mode*/) {
477 // TODO(petkov): Implement this.
478 NOTIMPLEMENTED();
479}
480
481void CellularCapabilityGSM::OnGSMRegistrationInfoChanged(
482 uint32 status, const string &operator_code, const string &operator_name) {
483 registration_state_ = status;
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100484 serving_operator_.SetCode(operator_code);
485 serving_operator_.SetName(operator_name);
Darin Petkovae0c64e2011-11-15 15:50:27 +0100486 UpdateOperatorInfo();
Darin Petkov184c54e2011-11-15 12:44:39 +0100487 cellular()->HandleNewRegistrationState();
488}
489
490void CellularCapabilityGSM::OnGSMSignalQualityChanged(uint32 quality) {
491 cellular()->HandleNewSignalQuality(quality);
492}
493
Darin Petkovdaf43862011-10-27 11:37:28 +0200494} // namespace shill