blob: 478db55faaca1a5a3889e26dbbc27a5f3764be3f [file] [log] [blame]
Chris Masone3bd3c8c2011-06-13 08:20:26 -07001// 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.h"
6
Darin Petkov0828f5f2011-08-11 10:18:52 -07007#include <netinet/in.h>
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -07008#include <linux/if.h> // Needs definitions from netinet/in.h
Darin Petkov0828f5f2011-08-11 10:18:52 -07009
Chris Masone3bd3c8c2011-06-13 08:20:26 -070010#include <string>
Chris Masone889666b2011-07-03 12:58:50 -070011#include <utility>
12#include <vector>
Chris Masone3bd3c8c2011-06-13 08:20:26 -070013
14#include <base/logging.h>
Darin Petkovc0865312011-09-16 15:31:20 -070015#include <base/string_number_conversions.h>
Darin Petkove9d12e02011-07-27 15:09:37 -070016#include <base/stringprintf.h>
Chris Masoneb925cc82011-06-22 15:39:57 -070017#include <chromeos/dbus/service_constants.h>
Darin Petkovbec79a22011-08-01 14:47:17 -070018#include <mm/mm-modem.h>
Darin Petkov137884a2011-10-26 18:52:47 +020019#include <mobile_provider.h>
Chris Masone3bd3c8c2011-06-13 08:20:26 -070020
Darin Petkovdaf43862011-10-27 11:37:28 +020021#include "shill/cellular_capability_cdma.h"
22#include "shill/cellular_capability_gsm.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070023#include "shill/cellular_service.h"
24#include "shill/control_interface.h"
25#include "shill/device.h"
26#include "shill/device_info.h"
Darin Petkov4d6d9412011-08-24 13:19:54 -070027#include "shill/error.h"
Paul Stewart26b327e2011-10-19 11:38:09 -070028#include "shill/event_dispatcher.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070029#include "shill/manager.h"
Darin Petkove604f702011-07-28 15:51:17 -070030#include "shill/modem_simple_proxy_interface.h"
Chris Masone7aa5f902011-07-11 11:13:35 -070031#include "shill/profile.h"
Chris Masone889666b2011-07-03 12:58:50 -070032#include "shill/property_accessor.h"
Darin Petkove9d12e02011-07-27 15:09:37 -070033#include "shill/proxy_factory.h"
Darin Petkov0828f5f2011-08-11 10:18:52 -070034#include "shill/rtnl_handler.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070035
Chris Masone889666b2011-07-03 12:58:50 -070036using std::make_pair;
Darin Petkovc0865312011-09-16 15:31:20 -070037using std::map;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070038using std::string;
Chris Masone889666b2011-07-03 12:58:50 -070039using std::vector;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070040
41namespace shill {
42
Darin Petkovc5f56562011-08-06 16:40:05 -070043const char Cellular::kConnectPropertyPhoneNumber[] = "number";
Darin Petkovc0865312011-09-16 15:31:20 -070044const char Cellular::kNetworkPropertyAccessTechnology[] = "access-tech";
45const char Cellular::kNetworkPropertyID[] = "operator-num";
46const char Cellular::kNetworkPropertyLongName[] = "operator-long";
47const char Cellular::kNetworkPropertyShortName[] = "operator-short";
48const char Cellular::kNetworkPropertyStatus[] = "status";
Darin Petkovc5f56562011-08-06 16:40:05 -070049const char Cellular::kPhoneNumberCDMA[] = "#777";
50const char Cellular::kPhoneNumberGSM[] = "*99#";
51
Darin Petkov3335b372011-08-22 11:05:32 -070052Cellular::Operator::Operator() {
53 SetName("");
54 SetCode("");
55 SetCountry("");
56}
57
58Cellular::Operator::~Operator() {}
59
60void Cellular::Operator::CopyFrom(const Operator &oper) {
61 dict_ = oper.dict_;
62}
63
64const string &Cellular::Operator::GetName() const {
65 return dict_.find(flimflam::kOperatorNameKey)->second;
66}
67
68void Cellular::Operator::SetName(const string &name) {
69 dict_[flimflam::kOperatorNameKey] = name;
70}
71
72const string &Cellular::Operator::GetCode() const {
73 return dict_.find(flimflam::kOperatorCodeKey)->second;
74}
75
76void Cellular::Operator::SetCode(const string &code) {
77 dict_[flimflam::kOperatorCodeKey] = code;
78}
79
80const string &Cellular::Operator::GetCountry() const {
81 return dict_.find(flimflam::kOperatorCountryKey)->second;
82}
83
84void Cellular::Operator::SetCountry(const string &country) {
85 dict_[flimflam::kOperatorCountryKey] = country;
86}
87
88const Stringmap &Cellular::Operator::ToDict() const {
89 return dict_;
90}
91
Darin Petkovbec79a22011-08-01 14:47:17 -070092Cellular::CDMA::CDMA()
93 : registration_state_evdo(MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN),
94 registration_state_1x(MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN),
Darin Petkovcc044422011-08-17 13:30:06 -070095 activation_state(MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED),
96 prl_version(0) {}
Darin Petkovbec79a22011-08-01 14:47:17 -070097
Darin Petkov9bac6fe2011-08-26 12:49:05 -070098Cellular::GSM::GSM()
99 : registration_state(MM_MODEM_GSM_NETWORK_REG_STATUS_UNKNOWN),
100 access_technology(MM_MODEM_GSM_ACCESS_TECH_UNKNOWN) {}
101
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700102Cellular::Cellular(ControlInterface *control_interface,
103 EventDispatcher *dispatcher,
104 Manager *manager,
Darin Petkove9d12e02011-07-27 15:09:37 -0700105 const string &link_name,
Darin Petkov3335b372011-08-22 11:05:32 -0700106 const string &address,
Darin Petkove9d12e02011-07-27 15:09:37 -0700107 int interface_index,
108 Type type,
109 const string &owner,
Darin Petkov137884a2011-10-26 18:52:47 +0200110 const string &path,
111 mobile_provider_db *provider_db)
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700112 : Device(control_interface,
113 dispatcher,
114 manager,
Darin Petkove9d12e02011-07-27 15:09:37 -0700115 link_name,
Chris Masone626719f2011-08-18 16:58:48 -0700116 address,
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700117 interface_index),
Darin Petkovab565bb2011-10-06 02:55:51 -0700118 proxy_factory_(ProxyFactory::GetInstance()),
Darin Petkove9d12e02011-07-27 15:09:37 -0700119 type_(type),
120 state_(kStateDisabled),
Darin Petkovbac96002011-08-09 13:22:00 -0700121 modem_state_(kModemStateUnknown),
Darin Petkove9d12e02011-07-27 15:09:37 -0700122 dbus_owner_(owner),
123 dbus_path_(path),
Darin Petkov137884a2011-10-26 18:52:47 +0200124 provider_db_(provider_db),
Darin Petkovc5f56562011-08-06 16:40:05 -0700125 task_factory_(this),
Darin Petkove9d12e02011-07-27 15:09:37 -0700126 allow_roaming_(false),
Darin Petkove9d12e02011-07-27 15:09:37 -0700127 scanning_(false),
128 scan_interval_(0) {
mukesh agrawalde29fa82011-09-16 16:16:36 -0700129 PropertyStore *store = this->mutable_store();
Paul Stewartac4ac002011-08-26 12:04:26 -0700130 store->RegisterConstString(flimflam::kCarrierProperty, &carrier_);
131 store->RegisterConstString(flimflam::kDBusConnectionProperty, &dbus_owner_);
132 store->RegisterConstString(flimflam::kDBusObjectProperty, &dbus_path_);
133 store->RegisterBool(flimflam::kCellularAllowRoamingProperty, &allow_roaming_);
134 store->RegisterConstString(flimflam::kEsnProperty, &esn_);
135 store->RegisterConstString(flimflam::kFirmwareRevisionProperty,
Chris Masone27c4aa52011-07-02 13:10:14 -0700136 &firmware_revision_);
Darin Petkovc0865312011-09-16 15:31:20 -0700137 store->RegisterConstStringmaps(flimflam::kFoundNetworksProperty,
138 &found_networks_);
Paul Stewartac4ac002011-08-26 12:04:26 -0700139 store->RegisterConstString(flimflam::kHardwareRevisionProperty,
Chris Masone27c4aa52011-07-02 13:10:14 -0700140 &hardware_revision_);
Paul Stewartac4ac002011-08-26 12:04:26 -0700141 store->RegisterConstStringmap(flimflam::kHomeProviderProperty,
Darin Petkov3335b372011-08-22 11:05:32 -0700142 &home_provider_.ToDict());
Paul Stewartac4ac002011-08-26 12:04:26 -0700143 store->RegisterConstString(flimflam::kImeiProperty, &imei_);
144 store->RegisterConstString(flimflam::kImsiProperty, &imsi_);
145 store->RegisterConstString(flimflam::kManufacturerProperty, &manufacturer_);
146 store->RegisterConstString(flimflam::kMdnProperty, &mdn_);
147 store->RegisterConstString(flimflam::kMeidProperty, &meid_);
148 store->RegisterConstString(flimflam::kMinProperty, &min_);
149 store->RegisterConstString(flimflam::kModelIDProperty, &model_id_);
150 store->RegisterConstUint16(flimflam::kPRLVersionProperty, &cdma_.prl_version);
151 store->RegisterConstString(flimflam::kSelectedNetworkProperty,
Darin Petkova1e0a1c2011-08-25 15:08:33 -0700152 &selected_network_);
Chris Masoneb925cc82011-06-22 15:39:57 -0700153
Chris Masone889666b2011-07-03 12:58:50 -0700154 HelpRegisterDerivedStrIntPair(flimflam::kSIMLockStatusProperty,
155 &Cellular::SimLockStatusToProperty,
156 NULL);
Chris Masoneb925cc82011-06-22 15:39:57 -0700157
Paul Stewartac4ac002011-08-26 12:04:26 -0700158 store->RegisterConstBool(flimflam::kScanningProperty, &scanning_);
159 store->RegisterUint16(flimflam::kScanIntervalProperty, &scan_interval_);
Chris Masone4d42df82011-07-02 17:09:39 -0700160
Paul Stewartac4ac002011-08-26 12:04:26 -0700161 VLOG(2) << "Cellular device " << this->link_name() << " initialized: "
Darin Petkove9d12e02011-07-27 15:09:37 -0700162 << GetTypeString();
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700163}
164
Darin Petkove9d12e02011-07-27 15:09:37 -0700165Cellular::~Cellular() {}
166
Darin Petkovcc044422011-08-17 13:30:06 -0700167string Cellular::GetTypeString() const {
Darin Petkove9d12e02011-07-27 15:09:37 -0700168 switch (type_) {
169 case kTypeGSM: return "CellularTypeGSM";
170 case kTypeCDMA: return "CellularTypeCDMA";
Darin Petkov0828f5f2011-08-11 10:18:52 -0700171 default: NOTREACHED();
Darin Petkove9d12e02011-07-27 15:09:37 -0700172 }
Darin Petkov0828f5f2011-08-11 10:18:52 -0700173 return StringPrintf("CellularTypeUnknown-%d", type_);
Darin Petkove9d12e02011-07-27 15:09:37 -0700174}
175
Darin Petkovcc044422011-08-17 13:30:06 -0700176// static
177string Cellular::GetStateString(State state) {
178 switch (state) {
Darin Petkove9d12e02011-07-27 15:09:37 -0700179 case kStateDisabled: return "CellularStateDisabled";
180 case kStateEnabled: return "CellularStateEnabled";
181 case kStateRegistered: return "CellularStateRegistered";
182 case kStateConnected: return "CellularStateConnected";
Darin Petkov0828f5f2011-08-11 10:18:52 -0700183 case kStateLinked: return "CellularStateLinked";
184 default: NOTREACHED();
Darin Petkove9d12e02011-07-27 15:09:37 -0700185 }
Darin Petkovcc044422011-08-17 13:30:06 -0700186 return StringPrintf("CellularStateUnknown-%d", state);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700187}
188
Darin Petkovd2045802011-08-23 11:09:25 -0700189string Cellular::GetNetworkTechnologyString() const {
190 switch (type_) {
191 case kTypeGSM:
Darin Petkov9bac6fe2011-08-26 12:49:05 -0700192 if (gsm_.registration_state == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME ||
193 gsm_.registration_state == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING) {
194 switch (gsm_.access_technology) {
195 case MM_MODEM_GSM_ACCESS_TECH_GSM:
196 case MM_MODEM_GSM_ACCESS_TECH_GSM_COMPACT:
Darin Petkove1a3e242011-08-29 12:44:30 -0700197 return flimflam::kNetworkTechnologyGsm;
Darin Petkov9bac6fe2011-08-26 12:49:05 -0700198 case MM_MODEM_GSM_ACCESS_TECH_GPRS:
199 return flimflam::kNetworkTechnologyGprs;
200 case MM_MODEM_GSM_ACCESS_TECH_EDGE:
201 return flimflam::kNetworkTechnologyEdge;
202 case MM_MODEM_GSM_ACCESS_TECH_UMTS:
203 return flimflam::kNetworkTechnologyUmts;
204 case MM_MODEM_GSM_ACCESS_TECH_HSDPA:
205 case MM_MODEM_GSM_ACCESS_TECH_HSUPA:
206 case MM_MODEM_GSM_ACCESS_TECH_HSPA:
207 return flimflam::kNetworkTechnologyHspa;
208 case MM_MODEM_GSM_ACCESS_TECH_HSPA_PLUS:
209 return flimflam::kNetworkTechnologyHspaPlus;
210 default:
211 NOTREACHED();
212 }
213 }
Darin Petkovd2045802011-08-23 11:09:25 -0700214 break;
215 case kTypeCDMA:
216 if (cdma_.registration_state_evdo !=
217 MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN) {
218 return flimflam::kNetworkTechnologyEvdo;
219 }
220 if (cdma_.registration_state_1x !=
221 MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN) {
222 return flimflam::kNetworkTechnology1Xrtt;
223 }
224 break;
225 default:
226 NOTREACHED();
227 }
228 return "";
229}
230
231string Cellular::GetRoamingStateString() const {
232 switch (type_) {
233 case kTypeGSM:
Darin Petkov9bac6fe2011-08-26 12:49:05 -0700234 switch (gsm_.registration_state) {
235 case MM_MODEM_GSM_NETWORK_REG_STATUS_HOME:
236 return flimflam::kRoamingStateHome;
237 case MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING:
238 return flimflam::kRoamingStateRoaming;
239 default:
240 break;
241 }
Darin Petkovd2045802011-08-23 11:09:25 -0700242 break;
243 case kTypeCDMA: {
244 uint32 state = cdma_.registration_state_evdo;
245 if (state == MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN) {
246 state = cdma_.registration_state_1x;
247 }
248 switch (state) {
249 case MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN:
250 case MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED:
251 break;
252 case MM_MODEM_CDMA_REGISTRATION_STATE_HOME:
253 return flimflam::kRoamingStateHome;
254 case MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING:
255 return flimflam::kRoamingStateRoaming;
256 default:
257 NOTREACHED();
258 }
259 break;
260 }
261 default:
262 NOTREACHED();
263 }
264 return flimflam::kRoamingStateUnknown;
265}
266
Darin Petkovc408e692011-08-17 13:47:15 -0700267// static
268string Cellular::GetCDMAActivationStateString(uint32 state) {
269 switch (state) {
270 case MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED:
Darin Petkov51489002011-08-18 13:13:20 -0700271 return flimflam::kActivationStateActivated;
Darin Petkovc408e692011-08-17 13:47:15 -0700272 case MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING:
Darin Petkov51489002011-08-18 13:13:20 -0700273 return flimflam::kActivationStateActivating;
Darin Petkovc408e692011-08-17 13:47:15 -0700274 case MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED:
Darin Petkov51489002011-08-18 13:13:20 -0700275 return flimflam::kActivationStateNotActivated;
Darin Petkovc408e692011-08-17 13:47:15 -0700276 case MM_MODEM_CDMA_ACTIVATION_STATE_PARTIALLY_ACTIVATED:
Darin Petkov51489002011-08-18 13:13:20 -0700277 return flimflam::kActivationStatePartiallyActivated;
Darin Petkovc408e692011-08-17 13:47:15 -0700278 default:
Darin Petkov51489002011-08-18 13:13:20 -0700279 return flimflam::kActivationStateUnknown;
280 }
281}
282
283// static
284string Cellular::GetCDMAActivationErrorString(uint32 error) {
285 switch (error) {
286 case MM_MODEM_CDMA_ACTIVATION_ERROR_WRONG_RADIO_INTERFACE:
287 return flimflam::kErrorNeedEvdo;
288 case MM_MODEM_CDMA_ACTIVATION_ERROR_ROAMING:
289 return flimflam::kErrorNeedHomeNetwork;
290 case MM_MODEM_CDMA_ACTIVATION_ERROR_COULD_NOT_CONNECT:
291 case MM_MODEM_CDMA_ACTIVATION_ERROR_SECURITY_AUTHENTICATION_FAILED:
292 case MM_MODEM_CDMA_ACTIVATION_ERROR_PROVISIONING_FAILED:
293 return flimflam::kErrorOtaspFailed;
294 case MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR:
295 return "";
296 case MM_MODEM_CDMA_ACTIVATION_ERROR_NO_SIGNAL:
297 default:
298 return flimflam::kErrorActivationFailed;
Darin Petkovc408e692011-08-17 13:47:15 -0700299 }
300}
301
Darin Petkov0828f5f2011-08-11 10:18:52 -0700302void Cellular::SetState(State state) {
Darin Petkovcc044422011-08-17 13:30:06 -0700303 VLOG(2) << GetStateString(state_) << " -> " << GetStateString(state);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700304 state_ = state;
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700305}
306
307void Cellular::Start() {
Darin Petkovcc044422011-08-17 13:30:06 -0700308 LOG(INFO) << __func__ << ": " << GetStateString(state_);
Darin Petkov3335b372011-08-22 11:05:32 -0700309 Device::Start();
Darin Petkovdaf43862011-10-27 11:37:28 +0200310 InitCapability(); // For now, only a single capability is supported.
Darin Petkovbec79a22011-08-01 14:47:17 -0700311 InitProxies();
Darin Petkovf5f61e02011-07-29 11:35:40 -0700312 EnableModem();
Darin Petkovceb68172011-07-29 14:47:48 -0700313 if (type_ == kTypeGSM) {
314 RegisterGSMModem();
315 }
Darin Petkovf5f61e02011-07-29 11:35:40 -0700316 GetModemStatus();
Darin Petkovcb547732011-11-09 13:55:26 +0100317 capability_->GetIdentifiers();
Darin Petkovceb68172011-07-29 14:47:48 -0700318 if (type_ == kTypeGSM) {
319 GetGSMProperties();
320 }
321 GetModemInfo();
322 GetModemRegistrationState();
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700323}
324
325void Cellular::Stop() {
Darin Petkovdaf43862011-10-27 11:37:28 +0200326 capability_.reset();
Darin Petkove9d12e02011-07-27 15:09:37 -0700327 proxy_.reset();
Darin Petkove604f702011-07-28 15:51:17 -0700328 simple_proxy_.reset();
Darin Petkovbec79a22011-08-01 14:47:17 -0700329 cdma_proxy_.reset();
Darin Petkove42e1012011-08-31 12:35:04 -0700330 gsm_network_proxy_.reset();
Paul Stewartac4ac002011-08-26 12:04:26 -0700331 manager()->DeregisterService(service_);
Darin Petkove9d12e02011-07-27 15:09:37 -0700332 service_ = NULL; // Breaks a reference cycle.
Darin Petkov0828f5f2011-08-11 10:18:52 -0700333 SetState(kStateDisabled);
Darin Petkov3335b372011-08-22 11:05:32 -0700334 Device::Stop();
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700335}
336
Darin Petkovdaf43862011-10-27 11:37:28 +0200337void Cellular::InitCapability() {
338 VLOG(2) << __func__;
339 switch (type_) {
340 case kTypeGSM:
341 capability_.reset(new CellularCapabilityGSM(this));
342 break;
343 case kTypeCDMA:
344 capability_.reset(new CellularCapabilityCDMA(this));
345 break;
346 default: NOTREACHED();
347 }
348}
349
Darin Petkovbec79a22011-08-01 14:47:17 -0700350void Cellular::InitProxies() {
Darin Petkovcc044422011-08-17 13:30:06 -0700351 VLOG(2) << __func__;
Darin Petkovab565bb2011-10-06 02:55:51 -0700352 proxy_.reset(proxy_factory_->CreateModemProxy(this, dbus_path_, dbus_owner_));
Darin Petkovbec79a22011-08-01 14:47:17 -0700353 simple_proxy_.reset(
Darin Petkovab565bb2011-10-06 02:55:51 -0700354 proxy_factory_->CreateModemSimpleProxy(dbus_path_, dbus_owner_));
Darin Petkovdaf43862011-10-27 11:37:28 +0200355 capability_->InitProxies();
Darin Petkovbec79a22011-08-01 14:47:17 -0700356}
357
Darin Petkovf5f61e02011-07-29 11:35:40 -0700358void Cellular::EnableModem() {
359 CHECK_EQ(kStateDisabled, state_);
360 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
361 proxy_->Enable(true);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700362 SetState(kStateEnabled);
Darin Petkovf5f61e02011-07-29 11:35:40 -0700363}
364
365void Cellular::GetModemStatus() {
Darin Petkovceb68172011-07-29 14:47:48 -0700366 CHECK_EQ(kStateEnabled, state_);
Darin Petkovf5f61e02011-07-29 11:35:40 -0700367 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
368 DBusPropertiesMap properties = simple_proxy_->GetStatus();
Darin Petkovceb68172011-07-29 14:47:48 -0700369 if (DBusProperties::GetString(properties, "carrier", &carrier_) &&
370 type_ == kTypeCDMA) {
Darin Petkov3335b372011-08-22 11:05:32 -0700371 home_provider_.SetName(carrier_);
372 home_provider_.SetCode("");
373 home_provider_.SetCountry("us");
Darin Petkovf5f61e02011-07-29 11:35:40 -0700374 }
Darin Petkovceb68172011-07-29 14:47:48 -0700375 DBusProperties::GetString(properties, "meid", &meid_);
376 DBusProperties::GetString(properties, "imei", &imei_);
377 if (DBusProperties::GetString(properties, "imsi", &imsi_) &&
378 type_ == kTypeGSM) {
Darin Petkov137884a2011-10-26 18:52:47 +0200379 // TODO(petkov): Set GSM provider based on IMSI and SPN.
Darin Petkovceb68172011-07-29 14:47:48 -0700380 }
381 DBusProperties::GetString(properties, "esn", &esn_);
382 DBusProperties::GetString(properties, "mdn", &mdn_);
383 DBusProperties::GetString(properties, "min", &min_);
Darin Petkovceb68172011-07-29 14:47:48 -0700384 DBusProperties::GetString(
385 properties, "firmware_revision", &firmware_revision_);
Darin Petkovb27e5442011-08-16 14:36:45 -0700386
Darin Petkovd2045802011-08-23 11:09:25 -0700387 uint32 state = 0;
388 if (DBusProperties::GetUint32(properties, "state", &state)) {
389 modem_state_ = static_cast<ModemState>(state);
390 }
Darin Petkovb27e5442011-08-16 14:36:45 -0700391
Darin Petkovceb68172011-07-29 14:47:48 -0700392 if (type_ == kTypeCDMA) {
Darin Petkovc408e692011-08-17 13:47:15 -0700393 DBusProperties::GetUint32(
394 properties, "activation_state", &cdma_.activation_state);
Darin Petkovcc044422011-08-17 13:30:06 -0700395 DBusProperties::GetUint16(properties, "prl_version", &cdma_.prl_version);
Darin Petkovcc044422011-08-17 13:30:06 -0700396 // TODO(petkov): For now, get the payment and usage URLs from ModemManager
397 // to match flimflam. In the future, provide a plugin API to get these
398 // directly from the modem driver.
399 DBusProperties::GetString(properties, "payment_url", &cdma_.payment_url);
400 DBusProperties::GetString(properties, "usage_url", &cdma_.usage_url);
Darin Petkovceb68172011-07-29 14:47:48 -0700401 }
402}
403
Darin Petkovceb68172011-07-29 14:47:48 -0700404void Cellular::GetGSMProperties() {
Darin Petkov975b5e72011-08-30 11:48:08 -0700405 CHECK_EQ(kTypeGSM, type_);
Darin Petkov9bac6fe2011-08-26 12:49:05 -0700406 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
407 gsm_.access_technology = gsm_network_proxy_->AccessTechnology();
408 VLOG(2) << "GSM AccessTechnology: " << gsm_.access_technology;
Darin Petkovceb68172011-07-29 14:47:48 -0700409}
410
411void Cellular::RegisterGSMModem() {
Darin Petkov975b5e72011-08-30 11:48:08 -0700412 CHECK_EQ(kTypeGSM, type_);
Darin Petkov9ae310f2011-08-30 15:41:13 -0700413 LOG(INFO) << "Registering on \"" << selected_network_ << "\"";
Darin Petkova1e0a1c2011-08-25 15:08:33 -0700414 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
415 gsm_network_proxy_->Register(selected_network_);
Darin Petkov9ae310f2011-08-30 15:41:13 -0700416 // TODO(petkov): Handle registration failure including trying the home network
417 // when selected_network_ is not empty.
418}
419
420void Cellular::RegisterOnNetwork(const string &network_id, Error *error) {
421 LOG(INFO) << __func__ << "(" << network_id << ")";
422 if (type_ != kTypeGSM) {
Paul Stewartbe005172011-11-02 18:10:29 -0700423 Error::PopulateAndLog(error, Error::kNotSupported,
424 "Network registration supported only for GSM.");
Darin Petkov9ae310f2011-08-30 15:41:13 -0700425 return;
426 }
427 // Defer registration because we may be in a dbus-c++ callback.
428 dispatcher()->PostTask(
429 task_factory_.NewRunnableMethod(&Cellular::RegisterOnNetworkTask,
430 network_id));
431}
432
433void Cellular::RegisterOnNetworkTask(const string &network_id) {
434 LOG(INFO) << __func__ << "(" << network_id << ")";
Darin Petkove42e1012011-08-31 12:35:04 -0700435 CHECK_EQ(kTypeGSM, type_);
Darin Petkov9ae310f2011-08-30 15:41:13 -0700436 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
437 gsm_network_proxy_->Register(network_id);
438 // TODO(petkov): Handle registration failure.
439 selected_network_ = network_id;
Darin Petkovceb68172011-07-29 14:47:48 -0700440}
441
Darin Petkove42e1012011-08-31 12:35:04 -0700442void Cellular::RequirePIN(const string &pin, bool require, Error *error) {
Darin Petkovb05315f2011-11-07 10:14:25 +0100443 capability_->RequirePIN(pin, require, error);
Darin Petkove42e1012011-08-31 12:35:04 -0700444}
445
446void Cellular::EnterPIN(const string &pin, Error *error) {
Darin Petkovb05315f2011-11-07 10:14:25 +0100447 capability_->EnterPIN(pin, error);
Darin Petkove42e1012011-08-31 12:35:04 -0700448}
449
Darin Petkovb05315f2011-11-07 10:14:25 +0100450void Cellular::UnblockPIN(
451 const string &unblock_code, const string &pin, Error *error) {
452 capability_->UnblockPIN(unblock_code, pin, error);
Darin Petkove42e1012011-08-31 12:35:04 -0700453}
454
Darin Petkovb05315f2011-11-07 10:14:25 +0100455void Cellular::ChangePIN(
456 const string &old_pin, const string &new_pin, Error *error) {
457 capability_->ChangePIN(old_pin, new_pin, error);
Darin Petkove42e1012011-08-31 12:35:04 -0700458}
459
Darin Petkovceb68172011-07-29 14:47:48 -0700460void Cellular::GetModemInfo() {
Darin Petkovd2045802011-08-23 11:09:25 -0700461 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Darin Petkovceb68172011-07-29 14:47:48 -0700462 ModemProxyInterface::Info info = proxy_->GetInfo();
463 manufacturer_ = info._1;
464 model_id_ = info._2;
465 hardware_revision_ = info._3;
466 VLOG(2) << "ModemInfo: " << manufacturer_ << ", " << model_id_ << ", "
467 << hardware_revision_;
468}
469
470void Cellular::GetModemRegistrationState() {
Darin Petkovbec79a22011-08-01 14:47:17 -0700471 switch (type_) {
472 case kTypeGSM:
473 GetGSMRegistrationState();
474 break;
475 case kTypeCDMA:
476 GetCDMARegistrationState();
477 break;
478 default: NOTREACHED();
479 }
Darin Petkovd9661952011-08-03 16:25:42 -0700480 HandleNewRegistrationState();
Darin Petkovbec79a22011-08-01 14:47:17 -0700481}
482
483void Cellular::GetCDMARegistrationState() {
484 CHECK_EQ(kTypeCDMA, type_);
Darin Petkovd2045802011-08-23 11:09:25 -0700485 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Darin Petkovbec79a22011-08-01 14:47:17 -0700486 cdma_proxy_->GetRegistrationState(&cdma_.registration_state_1x,
487 &cdma_.registration_state_evdo);
488 VLOG(2) << "CDMA Registration: 1x(" << cdma_.registration_state_1x
489 << ") EVDO(" << cdma_.registration_state_evdo << ")";
Darin Petkovbec79a22011-08-01 14:47:17 -0700490}
491
492void Cellular::GetGSMRegistrationState() {
Darin Petkov9bac6fe2011-08-26 12:49:05 -0700493 CHECK_EQ(kTypeGSM, type_);
494 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
495 ModemGSMNetworkProxyInterface::RegistrationInfo info =
496 gsm_network_proxy_->GetRegistrationInfo();
497 gsm_.registration_state = info._1;
498 gsm_.network_id = info._2;
499 gsm_.operator_name = info._3;
500 VLOG(2) << "GSM Registration: " << gsm_.registration_state << ", "
501 << gsm_.network_id << ", " << gsm_.operator_name;
Darin Petkov137884a2011-10-26 18:52:47 +0200502 UpdateGSMOperatorInfo();
Darin Petkovceb68172011-07-29 14:47:48 -0700503}
504
Darin Petkovd9661952011-08-03 16:25:42 -0700505void Cellular::HandleNewRegistrationState() {
Paul Stewartac4ac002011-08-26 12:04:26 -0700506 dispatcher()->PostTask(
Darin Petkov0828f5f2011-08-11 10:18:52 -0700507 task_factory_.NewRunnableMethod(
508 &Cellular::HandleNewRegistrationStateTask));
509}
510
511void Cellular::HandleNewRegistrationStateTask() {
Darin Petkovd9661952011-08-03 16:25:42 -0700512 VLOG(2) << __func__;
Darin Petkovd2045802011-08-23 11:09:25 -0700513 const string network_tech = GetNetworkTechnologyString();
514 if (network_tech.empty()) {
Darin Petkovc408e692011-08-17 13:47:15 -0700515 if (state_ == kStateLinked) {
Paul Stewartac4ac002011-08-26 12:04:26 -0700516 manager()->DeregisterService(service_);
Darin Petkovc408e692011-08-17 13:47:15 -0700517 }
Darin Petkovd9661952011-08-03 16:25:42 -0700518 service_ = NULL;
Darin Petkov0828f5f2011-08-11 10:18:52 -0700519 if (state_ == kStateLinked ||
520 state_ == kStateConnected ||
521 state_ == kStateRegistered) {
522 SetState(kStateEnabled);
Darin Petkovd9661952011-08-03 16:25:42 -0700523 }
524 return;
525 }
Darin Petkovd9661952011-08-03 16:25:42 -0700526 if (state_ == kStateEnabled) {
Darin Petkov0828f5f2011-08-11 10:18:52 -0700527 SetState(kStateRegistered);
Darin Petkovd9661952011-08-03 16:25:42 -0700528 }
529 if (!service_.get()) {
530 // For now, no endpoint is created. Revisit if necessary.
531 CreateService();
532 }
533 GetModemSignalQuality();
Darin Petkov0828f5f2011-08-11 10:18:52 -0700534 if (state_ == kStateRegistered && modem_state_ == kModemStateConnected) {
535 SetState(kStateConnected);
536 EstablishLink();
537 }
Darin Petkovd2045802011-08-23 11:09:25 -0700538 service_->set_network_tech(network_tech);
539 service_->set_roaming_state(GetRoamingStateString());
Darin Petkovd9661952011-08-03 16:25:42 -0700540}
541
542void Cellular::GetModemSignalQuality() {
Darin Petkov0828f5f2011-08-11 10:18:52 -0700543 VLOG(2) << __func__;
Darin Petkovd9661952011-08-03 16:25:42 -0700544 uint32 strength = 0;
545 switch (type_) {
546 case kTypeGSM:
547 strength = GetGSMSignalQuality();
548 break;
549 case kTypeCDMA:
550 strength = GetCDMASignalQuality();
551 break;
552 default: NOTREACHED();
553 }
554 HandleNewSignalQuality(strength);
555}
556
557uint32 Cellular::GetCDMASignalQuality() {
Darin Petkov0828f5f2011-08-11 10:18:52 -0700558 VLOG(2) << __func__;
Darin Petkovd9661952011-08-03 16:25:42 -0700559 CHECK_EQ(kTypeCDMA, type_);
560 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
561 return cdma_proxy_->GetSignalQuality();
562}
563
564uint32 Cellular::GetGSMSignalQuality() {
Darin Petkov22b72bf2011-08-29 14:01:20 -0700565 VLOG(2) << __func__;
566 CHECK_EQ(kTypeGSM, type_);
567 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
568 return gsm_network_proxy_->GetSignalQuality();
Darin Petkovd9661952011-08-03 16:25:42 -0700569}
570
571void Cellular::HandleNewSignalQuality(uint32 strength) {
572 VLOG(2) << "Signal strength: " << strength;
573 if (service_.get()) {
574 service_->set_strength(strength);
575 }
576}
577
578void Cellular::CreateService() {
Darin Petkov0828f5f2011-08-11 10:18:52 -0700579 VLOG(2) << __func__;
Darin Petkovd9661952011-08-03 16:25:42 -0700580 CHECK(!service_.get());
581 service_ =
Paul Stewartac4ac002011-08-26 12:04:26 -0700582 new CellularService(control_interface(), dispatcher(), manager(), this);
Darin Petkovc408e692011-08-17 13:47:15 -0700583 switch (type_) {
584 case kTypeGSM:
Darin Petkov51489002011-08-18 13:13:20 -0700585 service_->set_activation_state(flimflam::kActivationStateActivated);
Darin Petkov137884a2011-10-26 18:52:47 +0200586 UpdateServingOperator();
Darin Petkovc408e692011-08-17 13:47:15 -0700587 break;
588 case kTypeCDMA:
589 service_->set_payment_url(cdma_.payment_url);
590 service_->set_usage_url(cdma_.usage_url);
Darin Petkov137884a2011-10-26 18:52:47 +0200591 UpdateServingOperator();
Darin Petkovc408e692011-08-17 13:47:15 -0700592 HandleNewCDMAActivationState(MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR);
593 break;
594 default:
595 NOTREACHED();
Darin Petkovcc044422011-08-17 13:30:06 -0700596 }
Darin Petkovf5f61e02011-07-29 11:35:40 -0700597}
598
Paul Stewartfdd16072011-09-16 12:41:35 -0700599bool Cellular::TechnologyIs(const Technology::Identifier type) const {
600 return type == Technology::kCellular;
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700601}
602
Darin Petkov4d6d9412011-08-24 13:19:54 -0700603void Cellular::Connect(Error *error) {
Darin Petkovc5f56562011-08-06 16:40:05 -0700604 VLOG(2) << __func__;
Darin Petkov0828f5f2011-08-11 10:18:52 -0700605 if (state_ == kStateConnected ||
606 state_ == kStateLinked) {
Paul Stewartbe005172011-11-02 18:10:29 -0700607 Error::PopulateAndLog(error, Error::kAlreadyConnected,
608 "Already connected; connection request ignored.");
Darin Petkovc5f56562011-08-06 16:40:05 -0700609 return;
610 }
611 CHECK_EQ(kStateRegistered, state_);
Darin Petkovd2045802011-08-23 11:09:25 -0700612
613 if (!allow_roaming_ &&
614 service_->roaming_state() == flimflam::kRoamingStateRoaming) {
Paul Stewartbe005172011-11-02 18:10:29 -0700615 Error::PopulateAndLog(error, Error::kNotOnHomeNetwork,
616 "Roaming disallowed; connection request ignored.");
Darin Petkov4d6d9412011-08-24 13:19:54 -0700617 CHECK(error);
Darin Petkovd2045802011-08-23 11:09:25 -0700618 return;
619 }
620
Darin Petkovc5f56562011-08-06 16:40:05 -0700621 DBusPropertiesMap properties;
622 const char *phone_number = NULL;
623 switch (type_) {
624 case kTypeGSM:
625 phone_number = kPhoneNumberGSM;
626 break;
627 case kTypeCDMA:
628 phone_number = kPhoneNumberCDMA;
629 break;
630 default: NOTREACHED();
631 }
632 properties[kConnectPropertyPhoneNumber].writer().append_string(phone_number);
633 // TODO(petkov): Setup apn and "home_only".
634
635 // Defer connect because we may be in a dbus-c++ callback.
Paul Stewartac4ac002011-08-26 12:04:26 -0700636 dispatcher()->PostTask(
Darin Petkovc5f56562011-08-06 16:40:05 -0700637 task_factory_.NewRunnableMethod(&Cellular::ConnectTask, properties));
638}
639
640void Cellular::ConnectTask(const DBusPropertiesMap &properties) {
641 VLOG(2) << __func__;
Darin Petkovbac96002011-08-09 13:22:00 -0700642 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Darin Petkovc5f56562011-08-06 16:40:05 -0700643 simple_proxy_->Connect(properties);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700644 SetState(kStateConnected);
Darin Petkovbac96002011-08-09 13:22:00 -0700645 EstablishLink();
646}
647
648void Cellular::EstablishLink() {
649 VLOG(2) << __func__;
Darin Petkov0828f5f2011-08-11 10:18:52 -0700650 CHECK_EQ(kStateConnected, state_);
651 unsigned int flags = 0;
Paul Stewartac4ac002011-08-26 12:04:26 -0700652 if (manager()->device_info()->GetFlags(interface_index(), &flags) &&
Darin Petkov0828f5f2011-08-11 10:18:52 -0700653 (flags & IFF_UP) != 0) {
654 LinkEvent(flags, IFF_UP);
655 return;
656 }
657 // TODO(petkov): Provide a timeout for a failed link-up request.
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700658 rtnl_handler()->SetInterfaceFlags(interface_index(), IFF_UP, IFF_UP);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700659}
660
661void Cellular::LinkEvent(unsigned int flags, unsigned int change) {
662 Device::LinkEvent(flags, change);
663 if ((flags & IFF_UP) != 0 && state_ == kStateConnected) {
Paul Stewartac4ac002011-08-26 12:04:26 -0700664 LOG(INFO) << link_name() << " is up.";
Darin Petkov0828f5f2011-08-11 10:18:52 -0700665 SetState(kStateLinked);
Paul Stewartac4ac002011-08-26 12:04:26 -0700666 manager()->RegisterService(service_);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700667 // TODO(petkov): For GSM, remember the APN.
Darin Petkov60b8c3b2011-08-25 11:03:20 -0700668 if (AcquireDHCPConfig()) {
669 SelectService(service_);
670 SetServiceState(Service::kStateConfiguring);
671 } else {
672 LOG(ERROR) << "Unable to acquire DHCP config.";
673 }
Darin Petkov0828f5f2011-08-11 10:18:52 -0700674 } else if ((flags & IFF_UP) == 0 && state_ == kStateLinked) {
675 SetState(kStateConnected);
Paul Stewartac4ac002011-08-26 12:04:26 -0700676 manager()->DeregisterService(service_);
Darin Petkov60b8c3b2011-08-25 11:03:20 -0700677 SelectService(NULL);
Darin Petkov77cb6812011-08-15 16:19:41 -0700678 DestroyIPConfig();
Darin Petkov0828f5f2011-08-11 10:18:52 -0700679 }
Darin Petkovc5f56562011-08-06 16:40:05 -0700680}
681
Darin Petkovc0865312011-09-16 15:31:20 -0700682void Cellular::Scan(Error *error) {
683 VLOG(2) << __func__;
684 if (type_ != kTypeGSM) {
Paul Stewartbe005172011-11-02 18:10:29 -0700685 Error::PopulateAndLog(error, Error::kNotSupported,
686 "Network scanning support for GSM only.");
Darin Petkovc0865312011-09-16 15:31:20 -0700687 return;
688 }
689 // Defer scan because we may be in a dbus-c++ callback.
690 dispatcher()->PostTask(
691 task_factory_.NewRunnableMethod(&Cellular::ScanTask));
692}
693
694void Cellular::ScanTask() {
695 VLOG(2) << __func__;
696 // TODO(petkov): Defer scan requests if a scan is in progress already.
697 CHECK_EQ(kTypeGSM, type_);
698 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583). This is a
699 // must for this call which is basically a stub at this point.
700 ModemGSMNetworkProxyInterface::ScanResults results =
701 gsm_network_proxy_->Scan();
702 found_networks_.clear();
703 for (ModemGSMNetworkProxyInterface::ScanResults::const_iterator it =
704 results.begin(); it != results.end(); ++it) {
705 found_networks_.push_back(ParseScanResult(*it));
706 }
707}
708
709Stringmap Cellular::ParseScanResult(
710 const ModemGSMNetworkProxyInterface::ScanResult &result) {
711 Stringmap parsed;
712 for (ModemGSMNetworkProxyInterface::ScanResult::const_iterator it =
713 result.begin(); it != result.end(); ++it) {
714 // TODO(petkov): Define these in system_api/service_constants.h. The
715 // numerical values are taken from 3GPP TS 27.007 Section 7.3.
716 static const char * const kStatusString[] = {
717 "unknown",
718 "available",
719 "current",
720 "forbidden",
721 };
Darin Petkovc0865312011-09-16 15:31:20 -0700722 static const char * const kTechnologyString[] = {
723 flimflam::kNetworkTechnologyGsm,
724 "GSM Compact",
725 flimflam::kNetworkTechnologyUmts,
726 flimflam::kNetworkTechnologyEdge,
727 "HSDPA",
728 "HSUPA",
729 flimflam::kNetworkTechnologyHspa,
730 };
731 VLOG(2) << "Network property: " << it->first << " = " << it->second;
732 if (it->first == kNetworkPropertyStatus) {
733 int status = 0;
734 if (base::StringToInt(it->second, &status) &&
735 status >= 0 &&
736 status < static_cast<int>(arraysize(kStatusString))) {
737 parsed[flimflam::kStatusProperty] = kStatusString[status];
738 } else {
739 LOG(ERROR) << "Unexpected status value: " << it->second;
740 }
741 } else if (it->first == kNetworkPropertyID) {
742 parsed[flimflam::kNetworkIdProperty] = it->second;
743 } else if (it->first == kNetworkPropertyLongName) {
744 parsed[flimflam::kLongNameProperty] = it->second;
745 } else if (it->first == kNetworkPropertyShortName) {
746 parsed[flimflam::kShortNameProperty] = it->second;
747 } else if (it->first == kNetworkPropertyAccessTechnology) {
748 int tech = 0;
749 if (base::StringToInt(it->second, &tech) &&
750 tech >= 0 &&
751 tech < static_cast<int>(arraysize(kTechnologyString))) {
752 parsed[flimflam::kTechnologyProperty] = kTechnologyString[tech];
753 } else {
754 LOG(ERROR) << "Unexpected technology value: " << it->second;
755 }
756 } else {
757 LOG(WARNING) << "Unknown network property ignored: " << it->first;
758 }
759 }
Darin Petkov137884a2011-10-26 18:52:47 +0200760 // If the long name is not available but the network ID is, look up the long
761 // name in the mobile provider database.
762 if ((!ContainsKey(parsed, flimflam::kLongNameProperty) ||
763 parsed[flimflam::kLongNameProperty].empty()) &&
764 ContainsKey(parsed, flimflam::kNetworkIdProperty)) {
765 mobile_provider *provider =
766 mobile_provider_lookup_by_network(
767 provider_db_, parsed[flimflam::kNetworkIdProperty].c_str());
768 if (provider) {
769 const char *long_name = mobile_provider_get_name(provider);
770 if (long_name && *long_name) {
771 parsed[flimflam::kLongNameProperty] = long_name;
772 }
773 }
774 }
Darin Petkovc0865312011-09-16 15:31:20 -0700775 return parsed;
776}
777
Darin Petkovb100ae72011-08-24 16:19:45 -0700778void Cellular::Activate(const string &carrier, Error *error) {
Darin Petkovc0865312011-09-16 15:31:20 -0700779 VLOG(2) << __func__ << "(" << carrier << ")";
Darin Petkovb100ae72011-08-24 16:19:45 -0700780 if (type_ != kTypeCDMA) {
Paul Stewartbe005172011-11-02 18:10:29 -0700781 Error::PopulateAndLog(error, Error::kInvalidArguments,
782 "Unable to activate non-CDMA modem.");
Darin Petkovb100ae72011-08-24 16:19:45 -0700783 return;
784 }
785 if (state_ != kStateEnabled &&
786 state_ != kStateRegistered) {
Paul Stewartbe005172011-11-02 18:10:29 -0700787 Error::PopulateAndLog(error, Error::kInvalidArguments,
788 "Unable to activate in " + GetStateString(state_));
Darin Petkovb100ae72011-08-24 16:19:45 -0700789 return;
790 }
Darin Petkovc408e692011-08-17 13:47:15 -0700791 // Defer connect because we may be in a dbus-c++ callback.
Paul Stewartac4ac002011-08-26 12:04:26 -0700792 dispatcher()->PostTask(
Darin Petkovc408e692011-08-17 13:47:15 -0700793 task_factory_.NewRunnableMethod(&Cellular::ActivateTask, carrier));
794}
795
796void Cellular::ActivateTask(const string &carrier) {
797 VLOG(2) << __func__ << "(" << carrier << ")";
Darin Petkovc0865312011-09-16 15:31:20 -0700798 CHECK_EQ(kTypeCDMA, type_);
Darin Petkovb100ae72011-08-24 16:19:45 -0700799 if (state_ != kStateEnabled &&
800 state_ != kStateRegistered) {
Darin Petkovc408e692011-08-17 13:47:15 -0700801 LOG(ERROR) << "Unable to activate in " << GetStateString(state_);
802 return;
803 }
804 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
805 uint32 status = cdma_proxy_->Activate(carrier);
806 if (status == MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR) {
807 cdma_.activation_state = MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING;
808 }
809 HandleNewCDMAActivationState(status);
810}
811
812void Cellular::HandleNewCDMAActivationState(uint32 error) {
813 if (!service_.get()) {
814 return;
815 }
816 service_->set_activation_state(
817 GetCDMAActivationStateString(cdma_.activation_state));
Darin Petkov51489002011-08-18 13:13:20 -0700818 service_->set_error(GetCDMAActivationErrorString(error));
Darin Petkovc408e692011-08-17 13:47:15 -0700819}
820
Darin Petkovb27e5442011-08-16 14:36:45 -0700821void Cellular::OnCDMAActivationStateChanged(
822 uint32 activation_state,
823 uint32 activation_error,
824 const DBusPropertiesMap &status_changes) {
825 CHECK_EQ(kTypeCDMA, type_);
826 DBusProperties::GetString(status_changes, "mdn", &mdn_);
827 DBusProperties::GetString(status_changes, "min", &min_);
Darin Petkovcc044422011-08-17 13:30:06 -0700828 if (DBusProperties::GetString(
829 status_changes, "payment_url", &cdma_.payment_url) &&
Darin Petkovb27e5442011-08-16 14:36:45 -0700830 service_.get()) {
Darin Petkovcc044422011-08-17 13:30:06 -0700831 service_->set_payment_url(cdma_.payment_url);
Darin Petkovb27e5442011-08-16 14:36:45 -0700832 }
Darin Petkovc408e692011-08-17 13:47:15 -0700833 cdma_.activation_state = activation_state;
834 HandleNewCDMAActivationState(activation_error);
Darin Petkovb27e5442011-08-16 14:36:45 -0700835}
836
Darin Petkovd9661952011-08-03 16:25:42 -0700837void Cellular::OnCDMARegistrationStateChanged(uint32 state_1x,
838 uint32 state_evdo) {
839 CHECK_EQ(kTypeCDMA, type_);
840 cdma_.registration_state_1x = state_1x;
841 cdma_.registration_state_evdo = state_evdo;
842 HandleNewRegistrationState();
843}
844
845void Cellular::OnCDMASignalQualityChanged(uint32 strength) {
846 CHECK_EQ(kTypeCDMA, type_);
847 HandleNewSignalQuality(strength);
848}
849
mukesh agrawal1830fa12011-09-26 14:31:40 -0700850void Cellular::OnGSMNetworkModeChanged(uint32 /*mode*/) {
Darin Petkova1e0a1c2011-08-25 15:08:33 -0700851 // TODO(petkov): Implement this.
852 NOTIMPLEMENTED();
853}
854
855void Cellular::OnGSMRegistrationInfoChanged(uint32 status,
856 const string &operator_code,
857 const string &operator_name) {
Darin Petkov9bac6fe2011-08-26 12:49:05 -0700858 CHECK_EQ(kTypeGSM, type_);
859 gsm_.registration_state = status;
860 gsm_.network_id = operator_code;
861 gsm_.operator_name = operator_name;
Darin Petkov137884a2011-10-26 18:52:47 +0200862 UpdateGSMOperatorInfo();
Darin Petkov9bac6fe2011-08-26 12:49:05 -0700863 HandleNewRegistrationState();
Darin Petkova1e0a1c2011-08-25 15:08:33 -0700864}
865
866void Cellular::OnGSMSignalQualityChanged(uint32 quality) {
Darin Petkov22b72bf2011-08-29 14:01:20 -0700867 CHECK_EQ(kTypeGSM, type_);
868 HandleNewSignalQuality(quality);
Darin Petkova1e0a1c2011-08-25 15:08:33 -0700869}
870
mukesh agrawal1830fa12011-09-26 14:31:40 -0700871void Cellular::OnModemStateChanged(uint32 /*old_state*/,
872 uint32 /*new_state*/,
873 uint32 /*reason*/) {
Darin Petkovc5f56562011-08-06 16:40:05 -0700874 // TODO(petkov): Implement this.
875 NOTIMPLEMENTED();
876}
877
Darin Petkov48a511a2011-09-15 10:33:37 -0700878void Cellular::SetGSMAccessTechnology(uint32 access_technology) {
879 CHECK_EQ(kTypeGSM, type_);
880 gsm_.access_technology = access_technology;
881 if (service_.get()) {
882 service_->set_network_tech(GetNetworkTechnologyString());
883 }
884}
885
Darin Petkov137884a2011-10-26 18:52:47 +0200886void Cellular::UpdateGSMOperatorInfo() {
887 if (!gsm_.network_id.empty()) {
888 VLOG(2) << "Looking up network id: " << gsm_.network_id;
889 mobile_provider *provider =
890 mobile_provider_lookup_by_network(provider_db_,
891 gsm_.network_id.c_str());
892 if (provider) {
893 const char *provider_name = mobile_provider_get_name(provider);
894 if (provider_name && *provider_name) {
895 gsm_.operator_name = provider_name;
896 gsm_.operator_country = provider->country;
897 VLOG(2) << "Operator name: " << gsm_.operator_name
898 << ", country: " << gsm_.operator_country;
899 }
900 } else {
901 VLOG(2) << "GSM provider not found.";
902 }
903 }
904 UpdateServingOperator();
905}
906
907void Cellular::UpdateServingOperator() {
908 if (!service_.get()) {
909 return;
910 }
911 switch (type_) {
912 case kTypeGSM: {
913 Operator oper;
914 oper.SetName(gsm_.operator_name);
915 oper.SetCode(gsm_.network_id);
916 oper.SetCountry(gsm_.operator_country);
917 service_->set_serving_operator(oper);
918 break;
919 }
920 case kTypeCDMA:
921 service_->set_serving_operator(home_provider_);
922 break;
923 default: NOTREACHED();
924 }
925}
926
Chris Masone889666b2011-07-03 12:58:50 -0700927StrIntPair Cellular::SimLockStatusToProperty() {
928 return StrIntPair(make_pair(flimflam::kSIMLockTypeProperty,
929 sim_lock_status_.lock_type),
930 make_pair(flimflam::kSIMLockRetriesLeftProperty,
931 sim_lock_status_.retries_left));
932}
933
Chris Masone889666b2011-07-03 12:58:50 -0700934void Cellular::HelpRegisterDerivedStrIntPair(
935 const string &name,
936 StrIntPair(Cellular::*get)(void),
mukesh agrawalffa3d042011-10-06 15:26:10 -0700937 void(Cellular::*set)(const StrIntPair&, Error *)) {
mukesh agrawalde29fa82011-09-16 16:16:36 -0700938 mutable_store()->RegisterDerivedStrIntPair(
Chris Masone889666b2011-07-03 12:58:50 -0700939 name,
940 StrIntPairAccessor(
941 new CustomAccessor<Cellular, StrIntPair>(this, get, set)));
942}
943
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700944} // namespace shill