blob: 7e5b9ef07dcfbb70a65be4b80e9cb28d4845f7f2 [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
14#include "shill/cellular.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 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) {
100 string imsi;
101 if (DBusProperties::GetString(properties, "imsi", &imsi)) {
102 // TODO(petkov): Set GSM provider based on IMSI and SPN.
103 }
104}
105
106void CellularCapabilityGSM::SetupConnectProperties(
107 DBusPropertiesMap *properties) {
108 (*properties)[Cellular::kConnectPropertyPhoneNumber].writer().append_string(
109 kPhoneNumber);
110 // TODO(petkov): Setup apn and "home_only".
111}
112
Darin Petkovcb547732011-11-09 13:55:26 +0100113void CellularCapabilityGSM::GetIdentifiers() {
114 VLOG(2) << __func__;
115 if (cellular()->imei().empty()) {
116 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
117 cellular()->set_imei(card_proxy_->GetIMEI());
118 VLOG(2) << "IMEI: " << cellular()->imei();
119 }
120 if (cellular()->imsi().empty()) {
121 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
122 cellular()->set_imsi(card_proxy_->GetIMSI());
123 VLOG(2) << "IMSI: " << cellular()->imsi();
124 }
Darin Petkovae0c64e2011-11-15 15:50:27 +0100125 if (spn_.empty()) {
Darin Petkovcb547732011-11-09 13:55:26 +0100126 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
127 try {
Darin Petkovae0c64e2011-11-15 15:50:27 +0100128 spn_ = card_proxy_->GetSPN();
129 VLOG(2) << "SPN: " << spn_;
Darin Petkovcb547732011-11-09 13:55:26 +0100130 } catch (const DBus::Error e) {
131 // Some modems don't support this call so catch the exception explicitly.
132 LOG(WARNING) << "Unable to obtain SPN: " << e.what();
133 }
134 }
135 if (cellular()->mdn().empty()) {
136 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
137 cellular()->set_mdn(card_proxy_->GetMSISDN());
138 VLOG(2) << "MSISDN/MDN: " << cellular()->mdn();
139 }
140}
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 Petkovae0c64e2011-11-15 15:50:27 +0100155 network_id_ = info._2;
156 operator_name_ = info._3;
157 VLOG(2) << "GSM Registration: " << registration_state_ << ", "
158 << network_id_ << ", " << operator_name_;
159 UpdateOperatorInfo();
Darin Petkov184c54e2011-11-15 12:44:39 +0100160 cellular()->HandleNewRegistrationState();
161}
162
163void CellularCapabilityGSM::GetProperties() {
164 VLOG(2) << __func__;
165 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
166 uint32 tech = network_proxy_->AccessTechnology();
Darin Petkovae0c64e2011-11-15 15:50:27 +0100167 SetAccessTechnology(tech);
Darin Petkov184c54e2011-11-15 12:44:39 +0100168 VLOG(2) << "GSM AccessTechnology: " << tech;
169}
170
Darin Petkovae0c64e2011-11-15 15:50:27 +0100171void CellularCapabilityGSM::UpdateOperatorInfo() {
172 VLOG(2) << __func__;
173 if (!network_id_.empty()) {
174 VLOG(2) << "Looking up network id: " << network_id_;
175 mobile_provider *provider =
176 mobile_provider_lookup_by_network(cellular()->provider_db(),
177 network_id_.c_str());
178 if (provider) {
179 const char *provider_name = mobile_provider_get_name(provider);
180 if (provider_name && *provider_name) {
181 operator_name_ = provider_name;
182 operator_country_ = provider->country;
183 VLOG(2) << "Operator name: " << operator_name_
184 << ", country: " << operator_country_;
185 }
186 } else {
187 VLOG(2) << "GSM provider not found.";
188 }
189 }
190 UpdateServingOperator();
191}
192
193void CellularCapabilityGSM::UpdateServingOperator() {
194 VLOG(2) << __func__;
195 if (!cellular()->service().get()) {
196 return;
197 }
198 Cellular::Operator oper;
199 oper.SetName(operator_name_);
200 oper.SetCode(network_id_);
201 oper.SetCountry(operator_country_);
202 cellular()->service()->set_serving_operator(oper);
203}
204
Darin Petkov184c54e2011-11-15 12:44:39 +0100205void CellularCapabilityGSM::Register() {
206 LOG(INFO) << __func__ << " \"" << selected_network_ << "\"";
207 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
208 network_proxy_->Register(selected_network_);
209 // TODO(petkov): Handle registration failure including trying the home network
210 // when selected_network_ is not empty.
211}
212
213void CellularCapabilityGSM::RegisterOnNetwork(
214 const string &network_id, Error */*error*/) {
215 LOG(INFO) << __func__ << "(" << network_id << ")";
216 // Defer because we may be in a dbus-c++ callback.
217 dispatcher()->PostTask(
218 task_factory_.NewRunnableMethod(
219 &CellularCapabilityGSM::RegisterOnNetworkTask,
220 network_id));
221}
222
223void CellularCapabilityGSM::RegisterOnNetworkTask(const string &network_id) {
224 LOG(INFO) << __func__ << "(" << network_id << ")";
225 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
226 network_proxy_->Register(network_id);
227 // TODO(petkov): Handle registration failure.
228 selected_network_ = network_id;
229}
230
Darin Petkovb05315f2011-11-07 10:14:25 +0100231void CellularCapabilityGSM::RequirePIN(
232 const string &pin, bool require, Error */*error*/) {
233 VLOG(2) << __func__ << "(" << pin << ", " << require << ")";
234 // Defer because we may be in a dbus-c++ callback.
235 dispatcher()->PostTask(
236 task_factory_.NewRunnableMethod(
237 &CellularCapabilityGSM::RequirePINTask, pin, require));
238}
239
240void CellularCapabilityGSM::RequirePINTask(const string &pin, bool require) {
241 VLOG(2) << __func__ << "(" << pin << ", " << require << ")";
242 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Darin Petkovcb547732011-11-09 13:55:26 +0100243 card_proxy_->EnablePIN(pin, require);
Darin Petkovb05315f2011-11-07 10:14:25 +0100244}
245
246void CellularCapabilityGSM::EnterPIN(const string &pin, Error */*error*/) {
247 VLOG(2) << __func__ << "(" << pin << ")";
248 // Defer because we may be in a dbus-c++ callback.
249 dispatcher()->PostTask(
250 task_factory_.NewRunnableMethod(
251 &CellularCapabilityGSM::EnterPINTask, pin));
252}
253
254void CellularCapabilityGSM::EnterPINTask(const string &pin) {
255 VLOG(2) << __func__ << "(" << pin << ")";
256 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Darin Petkovcb547732011-11-09 13:55:26 +0100257 card_proxy_->SendPIN(pin);
Darin Petkovb05315f2011-11-07 10:14:25 +0100258}
259
260void CellularCapabilityGSM::UnblockPIN(
261 const string &unblock_code, const string &pin, Error */*error*/) {
262 VLOG(2) << __func__ << "(" << unblock_code << ", " << pin << ")";
263 // Defer because we may be in a dbus-c++ callback.
264 dispatcher()->PostTask(
265 task_factory_.NewRunnableMethod(
266 &CellularCapabilityGSM::UnblockPINTask, unblock_code, pin));
267}
268
269void CellularCapabilityGSM::UnblockPINTask(
270 const string &unblock_code, const string &pin) {
271 VLOG(2) << __func__ << "(" << unblock_code << ", " << pin << ")";
272 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Darin Petkovcb547732011-11-09 13:55:26 +0100273 card_proxy_->SendPUK(unblock_code, pin);
Darin Petkovb05315f2011-11-07 10:14:25 +0100274}
275
276void CellularCapabilityGSM::ChangePIN(
277 const string &old_pin, const string &new_pin, Error */*error*/) {
278 VLOG(2) << __func__ << "(" << old_pin << ", " << new_pin << ")";
279 // Defer because we may be in a dbus-c++ callback.
280 dispatcher()->PostTask(
281 task_factory_.NewRunnableMethod(
282 &CellularCapabilityGSM::ChangePINTask, old_pin, new_pin));
283}
284
285void CellularCapabilityGSM::ChangePINTask(
286 const string &old_pin, const string &new_pin) {
287 VLOG(2) << __func__ << "(" << old_pin << ", " << new_pin << ")";
288 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Darin Petkovcb547732011-11-09 13:55:26 +0100289 card_proxy_->ChangePIN(old_pin, new_pin);
Darin Petkovb05315f2011-11-07 10:14:25 +0100290}
291
Darin Petkov1272a432011-11-10 15:53:37 +0100292void CellularCapabilityGSM::Scan(Error */*error*/) {
293 VLOG(2) << __func__;
294 // Defer because we may be in a dbus-c++ callback.
295 dispatcher()->PostTask(
296 task_factory_.NewRunnableMethod(&CellularCapabilityGSM::ScanTask));
297}
298
299void CellularCapabilityGSM::ScanTask() {
300 VLOG(2) << __func__;
301 // TODO(petkov): Defer scan requests if a scan is in progress already.
302 //
303 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583). This is a
304 // must for this call which is basically a stub at this point.
Darin Petkov184c54e2011-11-15 12:44:39 +0100305 ModemGSMNetworkProxyInterface::ScanResults results = network_proxy_->Scan();
Darin Petkov1272a432011-11-10 15:53:37 +0100306 found_networks_.clear();
307 for (ModemGSMNetworkProxyInterface::ScanResults::const_iterator it =
308 results.begin(); it != results.end(); ++it) {
309 found_networks_.push_back(ParseScanResult(*it));
310 }
311}
312
313Stringmap CellularCapabilityGSM::ParseScanResult(
314 const ModemGSMNetworkProxyInterface::ScanResult &result) {
315 Stringmap parsed;
316 for (ModemGSMNetworkProxyInterface::ScanResult::const_iterator it =
317 result.begin(); it != result.end(); ++it) {
318 // TODO(petkov): Define these in system_api/service_constants.h. The
319 // numerical values are taken from 3GPP TS 27.007 Section 7.3.
320 static const char * const kStatusString[] = {
321 "unknown",
322 "available",
323 "current",
324 "forbidden",
325 };
326 static const char * const kTechnologyString[] = {
327 flimflam::kNetworkTechnologyGsm,
328 "GSM Compact",
329 flimflam::kNetworkTechnologyUmts,
330 flimflam::kNetworkTechnologyEdge,
331 "HSDPA",
332 "HSUPA",
333 flimflam::kNetworkTechnologyHspa,
334 };
335 VLOG(2) << "Network property: " << it->first << " = " << it->second;
336 if (it->first == kNetworkPropertyStatus) {
337 int status = 0;
338 if (base::StringToInt(it->second, &status) &&
339 status >= 0 &&
340 status < static_cast<int>(arraysize(kStatusString))) {
341 parsed[flimflam::kStatusProperty] = kStatusString[status];
342 } else {
343 LOG(ERROR) << "Unexpected status value: " << it->second;
344 }
345 } else if (it->first == kNetworkPropertyID) {
346 parsed[flimflam::kNetworkIdProperty] = it->second;
347 } else if (it->first == kNetworkPropertyLongName) {
348 parsed[flimflam::kLongNameProperty] = it->second;
349 } else if (it->first == kNetworkPropertyShortName) {
350 parsed[flimflam::kShortNameProperty] = it->second;
351 } else if (it->first == kNetworkPropertyAccessTechnology) {
352 int tech = 0;
353 if (base::StringToInt(it->second, &tech) &&
354 tech >= 0 &&
355 tech < static_cast<int>(arraysize(kTechnologyString))) {
356 parsed[flimflam::kTechnologyProperty] = kTechnologyString[tech];
357 } else {
358 LOG(ERROR) << "Unexpected technology value: " << it->second;
359 }
360 } else {
361 LOG(WARNING) << "Unknown network property ignored: " << it->first;
362 }
363 }
364 // If the long name is not available but the network ID is, look up the long
365 // name in the mobile provider database.
366 if ((!ContainsKey(parsed, flimflam::kLongNameProperty) ||
367 parsed[flimflam::kLongNameProperty].empty()) &&
368 ContainsKey(parsed, flimflam::kNetworkIdProperty)) {
369 mobile_provider *provider =
370 mobile_provider_lookup_by_network(
371 cellular()->provider_db(),
372 parsed[flimflam::kNetworkIdProperty].c_str());
373 if (provider) {
374 const char *long_name = mobile_provider_get_name(provider);
375 if (long_name && *long_name) {
376 parsed[flimflam::kLongNameProperty] = long_name;
377 }
378 }
379 }
380 return parsed;
381}
382
Darin Petkovae0c64e2011-11-15 15:50:27 +0100383void CellularCapabilityGSM::SetAccessTechnology(uint32 access_technology) {
384 access_technology_ = access_technology;
385 if (cellular()->service().get()) {
386 cellular()->service()->set_network_tech(GetNetworkTechnologyString());
387 }
388}
389
Darin Petkov20c13ec2011-11-09 15:07:15 +0100390string CellularCapabilityGSM::GetNetworkTechnologyString() const {
Darin Petkov184c54e2011-11-15 12:44:39 +0100391 if (registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME ||
392 registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING) {
Darin Petkovae0c64e2011-11-15 15:50:27 +0100393 switch (access_technology_) {
Darin Petkov20c13ec2011-11-09 15:07:15 +0100394 case MM_MODEM_GSM_ACCESS_TECH_GSM:
395 case MM_MODEM_GSM_ACCESS_TECH_GSM_COMPACT:
396 return flimflam::kNetworkTechnologyGsm;
397 case MM_MODEM_GSM_ACCESS_TECH_GPRS:
398 return flimflam::kNetworkTechnologyGprs;
399 case MM_MODEM_GSM_ACCESS_TECH_EDGE:
400 return flimflam::kNetworkTechnologyEdge;
401 case MM_MODEM_GSM_ACCESS_TECH_UMTS:
402 return flimflam::kNetworkTechnologyUmts;
403 case MM_MODEM_GSM_ACCESS_TECH_HSDPA:
404 case MM_MODEM_GSM_ACCESS_TECH_HSUPA:
405 case MM_MODEM_GSM_ACCESS_TECH_HSPA:
406 return flimflam::kNetworkTechnologyHspa;
407 case MM_MODEM_GSM_ACCESS_TECH_HSPA_PLUS:
408 return flimflam::kNetworkTechnologyHspaPlus;
409 default:
410 NOTREACHED();
411 }
412 }
413 return "";
414}
415
416string CellularCapabilityGSM::GetRoamingStateString() const {
Darin Petkov184c54e2011-11-15 12:44:39 +0100417 switch (registration_state_) {
Darin Petkov20c13ec2011-11-09 15:07:15 +0100418 case MM_MODEM_GSM_NETWORK_REG_STATUS_HOME:
419 return flimflam::kRoamingStateHome;
420 case MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING:
421 return flimflam::kRoamingStateRoaming;
422 default:
423 break;
424 }
425 return flimflam::kRoamingStateUnknown;
426}
427
Darin Petkovae0c64e2011-11-15 15:50:27 +0100428void CellularCapabilityGSM::OnModemManagerPropertiesChanged(
429 const DBusPropertiesMap &properties) {
430 uint32 access_technology = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN;
431 if (DBusProperties::GetUint32(properties,
432 kPropertyAccessTechnology,
433 &access_technology)) {
434 SetAccessTechnology(access_technology);
435 }
Darin Petkov721ac932011-11-16 15:43:09 +0100436 DBusProperties::GetString(
437 properties, kPropertyUnlockRequired, &sim_lock_status_.lock_type);
438 DBusProperties::GetUint32(
439 properties, kPropertyUnlockRetries, &sim_lock_status_.retries_left);
Darin Petkovae0c64e2011-11-15 15:50:27 +0100440}
441
Darin Petkov184c54e2011-11-15 12:44:39 +0100442void CellularCapabilityGSM::OnGSMNetworkModeChanged(uint32 /*mode*/) {
443 // TODO(petkov): Implement this.
444 NOTIMPLEMENTED();
445}
446
447void CellularCapabilityGSM::OnGSMRegistrationInfoChanged(
448 uint32 status, const string &operator_code, const string &operator_name) {
449 registration_state_ = status;
Darin Petkovae0c64e2011-11-15 15:50:27 +0100450 network_id_ = operator_code;
451 operator_name_ = operator_name;
452 UpdateOperatorInfo();
Darin Petkov184c54e2011-11-15 12:44:39 +0100453 cellular()->HandleNewRegistrationState();
454}
455
456void CellularCapabilityGSM::OnGSMSignalQualityChanged(uint32 quality) {
457 cellular()->HandleNewSignalQuality(quality);
458}
459
Darin Petkovdaf43862011-10-27 11:37:28 +0200460} // namespace shill