blob: 989ab75214fd370a8f3970534041cd4694a3c208 [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>
8#include <linux/if.h>
9
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 Petkove9d12e02011-07-27 15:09:37 -070015#include <base/stringprintf.h>
Chris Masoneb925cc82011-06-22 15:39:57 -070016#include <chromeos/dbus/service_constants.h>
Darin Petkovbec79a22011-08-01 14:47:17 -070017#include <mm/mm-modem.h>
Chris Masone3bd3c8c2011-06-13 08:20:26 -070018
19#include "shill/cellular_service.h"
20#include "shill/control_interface.h"
21#include "shill/device.h"
22#include "shill/device_info.h"
23#include "shill/manager.h"
Darin Petkove604f702011-07-28 15:51:17 -070024#include "shill/modem_simple_proxy_interface.h"
Chris Masone7aa5f902011-07-11 11:13:35 -070025#include "shill/profile.h"
Chris Masone889666b2011-07-03 12:58:50 -070026#include "shill/property_accessor.h"
Darin Petkove9d12e02011-07-27 15:09:37 -070027#include "shill/proxy_factory.h"
Darin Petkov0828f5f2011-08-11 10:18:52 -070028#include "shill/rtnl_handler.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070029#include "shill/shill_event.h"
30
Chris Masone889666b2011-07-03 12:58:50 -070031using std::make_pair;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070032using std::string;
Chris Masone889666b2011-07-03 12:58:50 -070033using std::vector;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070034
35namespace shill {
36
Darin Petkovc408e692011-08-17 13:47:15 -070037const char Cellular::kActivationStateActivated[] = "activated";
38const char Cellular::kActivationStateActivating[] = "activating";
39const char Cellular::kActivationStateNotActivated[] = "not-activated";
40const char Cellular::kActivationStatePartiallyActivated[] =
41 "partially-activated";
42const char Cellular::kActivationStateUnknown[] = "unknown";
Darin Petkovc5f56562011-08-06 16:40:05 -070043const char Cellular::kConnectPropertyPhoneNumber[] = "number";
44const char Cellular::kPhoneNumberCDMA[] = "#777";
45const char Cellular::kPhoneNumberGSM[] = "*99#";
46
Chris Masone889666b2011-07-03 12:58:50 -070047Cellular::Network::Network() {
48 dict_[flimflam::kStatusProperty] = "";
49 dict_[flimflam::kNetworkIdProperty] = "";
50 dict_[flimflam::kShortNameProperty] = "";
51 dict_[flimflam::kLongNameProperty] = "";
52 dict_[flimflam::kTechnologyProperty] = "";
53}
54
55Cellular::Network::~Network() {}
56
57const std::string &Cellular::Network::GetStatus() const {
58 return dict_.find(flimflam::kStatusProperty)->second;
59}
60
61void Cellular::Network::SetStatus(const std::string &status) {
62 dict_[flimflam::kStatusProperty] = status;
63}
64
65const std::string &Cellular::Network::GetId() const {
66 return dict_.find(flimflam::kNetworkIdProperty)->second;
67}
68
69void Cellular::Network::SetId(const std::string &id) {
70 dict_[flimflam::kNetworkIdProperty] = id;
71}
72
73const std::string &Cellular::Network::GetShortName() const {
74 return dict_.find(flimflam::kShortNameProperty)->second;
75}
76
77void Cellular::Network::SetShortName(const std::string &name) {
78 dict_[flimflam::kShortNameProperty] = name;
79}
80
81const std::string &Cellular::Network::GetLongName() const {
82 return dict_.find(flimflam::kLongNameProperty)->second;
83}
84
85void Cellular::Network::SetLongName(const std::string &name) {
86 dict_[flimflam::kLongNameProperty] = name;
87}
88
89const std::string &Cellular::Network::GetTechnology() const {
90 return dict_.find(flimflam::kTechnologyProperty)->second;
91}
92
93void Cellular::Network::SetTechnology(const std::string &technology) {
94 dict_[flimflam::kTechnologyProperty] = technology;
95}
96
97const Stringmap &Cellular::Network::ToDict() const {
98 return dict_;
99}
100
Darin Petkovbec79a22011-08-01 14:47:17 -0700101Cellular::CDMA::CDMA()
102 : registration_state_evdo(MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN),
103 registration_state_1x(MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN),
Darin Petkovcc044422011-08-17 13:30:06 -0700104 activation_state(MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED),
105 prl_version(0) {}
Darin Petkovbec79a22011-08-01 14:47:17 -0700106
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700107Cellular::Cellular(ControlInterface *control_interface,
108 EventDispatcher *dispatcher,
109 Manager *manager,
Darin Petkove9d12e02011-07-27 15:09:37 -0700110 const string &link_name,
111 int interface_index,
112 Type type,
113 const string &owner,
114 const string &path)
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700115 : Device(control_interface,
116 dispatcher,
117 manager,
Darin Petkove9d12e02011-07-27 15:09:37 -0700118 link_name,
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700119 interface_index),
Darin Petkove9d12e02011-07-27 15:09:37 -0700120 type_(type),
121 state_(kStateDisabled),
Darin Petkovbac96002011-08-09 13:22:00 -0700122 modem_state_(kModemStateUnknown),
Darin Petkove9d12e02011-07-27 15:09:37 -0700123 dbus_owner_(owner),
124 dbus_path_(path),
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) {
129 store_.RegisterConstString(flimflam::kDBusConnectionProperty, &dbus_owner_);
130 store_.RegisterConstString(flimflam::kDBusObjectProperty, &dbus_path_);
Chris Masone27c4aa52011-07-02 13:10:14 -0700131 store_.RegisterConstString(flimflam::kCarrierProperty, &carrier_);
Chris Masone4d42df82011-07-02 17:09:39 -0700132 store_.RegisterBool(flimflam::kCellularAllowRoamingProperty, &allow_roaming_);
Chris Masone27c4aa52011-07-02 13:10:14 -0700133 store_.RegisterConstString(flimflam::kEsnProperty, &esn_);
Chris Masone27c4aa52011-07-02 13:10:14 -0700134 store_.RegisterConstString(flimflam::kFirmwareRevisionProperty,
135 &firmware_revision_);
136 store_.RegisterConstString(flimflam::kHardwareRevisionProperty,
137 &hardware_revision_);
Chris Masone4d42df82011-07-02 17:09:39 -0700138 store_.RegisterConstString(flimflam::kImeiProperty, &imei_);
139 store_.RegisterConstString(flimflam::kImsiProperty, &imsi_);
140 store_.RegisterConstString(flimflam::kManufacturerProperty, &manufacturer_);
141 store_.RegisterConstString(flimflam::kMdnProperty, &mdn_);
142 store_.RegisterConstString(flimflam::kMeidProperty, &meid_);
143 store_.RegisterConstString(flimflam::kMinProperty, &min_);
144 store_.RegisterConstString(flimflam::kModelIDProperty, &model_id_);
Darin Petkovcc044422011-08-17 13:30:06 -0700145 store_.RegisterConstUint16(flimflam::kPRLVersionProperty, &cdma_.prl_version);
Chris Masoneb925cc82011-06-22 15:39:57 -0700146
Chris Masone889666b2011-07-03 12:58:50 -0700147 HelpRegisterDerivedStrIntPair(flimflam::kSIMLockStatusProperty,
148 &Cellular::SimLockStatusToProperty,
149 NULL);
150 HelpRegisterDerivedStringmaps(flimflam::kFoundNetworksProperty,
151 &Cellular::EnumerateNetworks,
152 NULL);
Chris Masoneb925cc82011-06-22 15:39:57 -0700153
Chris Masone4d42df82011-07-02 17:09:39 -0700154 store_.RegisterConstBool(flimflam::kScanningProperty, &scanning_);
155 store_.RegisterUint16(flimflam::kScanIntervalProperty, &scan_interval_);
156
Darin Petkove9d12e02011-07-27 15:09:37 -0700157 VLOG(2) << "Cellular device " << link_name_ << " initialized: "
158 << GetTypeString();
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700159}
160
Darin Petkove9d12e02011-07-27 15:09:37 -0700161Cellular::~Cellular() {}
162
Darin Petkovcc044422011-08-17 13:30:06 -0700163string Cellular::GetTypeString() const {
Darin Petkove9d12e02011-07-27 15:09:37 -0700164 switch (type_) {
165 case kTypeGSM: return "CellularTypeGSM";
166 case kTypeCDMA: return "CellularTypeCDMA";
Darin Petkov0828f5f2011-08-11 10:18:52 -0700167 default: NOTREACHED();
Darin Petkove9d12e02011-07-27 15:09:37 -0700168 }
Darin Petkov0828f5f2011-08-11 10:18:52 -0700169 return StringPrintf("CellularTypeUnknown-%d", type_);
Darin Petkove9d12e02011-07-27 15:09:37 -0700170}
171
Darin Petkovcc044422011-08-17 13:30:06 -0700172// static
173string Cellular::GetStateString(State state) {
174 switch (state) {
Darin Petkove9d12e02011-07-27 15:09:37 -0700175 case kStateDisabled: return "CellularStateDisabled";
176 case kStateEnabled: return "CellularStateEnabled";
177 case kStateRegistered: return "CellularStateRegistered";
178 case kStateConnected: return "CellularStateConnected";
Darin Petkov0828f5f2011-08-11 10:18:52 -0700179 case kStateLinked: return "CellularStateLinked";
180 default: NOTREACHED();
Darin Petkove9d12e02011-07-27 15:09:37 -0700181 }
Darin Petkovcc044422011-08-17 13:30:06 -0700182 return StringPrintf("CellularStateUnknown-%d", state);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700183}
184
Darin Petkovc408e692011-08-17 13:47:15 -0700185// static
186string Cellular::GetCDMAActivationStateString(uint32 state) {
187 switch (state) {
188 case MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED:
189 return kActivationStateActivated;
190 case MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING:
191 return kActivationStateActivating;
192 case MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED:
193 return kActivationStateNotActivated;
194 case MM_MODEM_CDMA_ACTIVATION_STATE_PARTIALLY_ACTIVATED:
195 return kActivationStatePartiallyActivated;
196 default:
197 return kActivationStateUnknown;
198 }
199}
200
Darin Petkov0828f5f2011-08-11 10:18:52 -0700201void Cellular::SetState(State state) {
Darin Petkovcc044422011-08-17 13:30:06 -0700202 VLOG(2) << GetStateString(state_) << " -> " << GetStateString(state);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700203 state_ = state;
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700204}
205
206void Cellular::Start() {
Darin Petkovcc044422011-08-17 13:30:06 -0700207 LOG(INFO) << __func__ << ": " << GetStateString(state_);
Darin Petkovbec79a22011-08-01 14:47:17 -0700208 InitProxies();
Darin Petkovf5f61e02011-07-29 11:35:40 -0700209 EnableModem();
Darin Petkovceb68172011-07-29 14:47:48 -0700210 if (type_ == kTypeGSM) {
211 RegisterGSMModem();
212 }
Darin Petkovf5f61e02011-07-29 11:35:40 -0700213 GetModemStatus();
Darin Petkovceb68172011-07-29 14:47:48 -0700214 GetModemIdentifiers();
215 if (type_ == kTypeGSM) {
216 GetGSMProperties();
217 }
218 GetModemInfo();
219 GetModemRegistrationState();
Darin Petkove9d12e02011-07-27 15:09:37 -0700220 // TODO(petkov): Device::Start();
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700221}
222
223void Cellular::Stop() {
Darin Petkove9d12e02011-07-27 15:09:37 -0700224 proxy_.reset();
Darin Petkove604f702011-07-28 15:51:17 -0700225 simple_proxy_.reset();
Darin Petkovbec79a22011-08-01 14:47:17 -0700226 cdma_proxy_.reset();
Chris Masone2b105542011-06-22 10:58:09 -0700227 manager_->DeregisterService(service_);
Darin Petkove9d12e02011-07-27 15:09:37 -0700228 service_ = NULL; // Breaks a reference cycle.
Darin Petkov0828f5f2011-08-11 10:18:52 -0700229 SetState(kStateDisabled);
230 RTNLHandler::GetInstance()->SetInterfaceFlags(interface_index_, 0, IFF_UP);
Darin Petkove9d12e02011-07-27 15:09:37 -0700231 // TODO(petkov): Device::Stop();
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700232}
233
Darin Petkovbec79a22011-08-01 14:47:17 -0700234void Cellular::InitProxies() {
Darin Petkovcc044422011-08-17 13:30:06 -0700235 VLOG(2) << __func__;
Darin Petkovbec79a22011-08-01 14:47:17 -0700236 proxy_.reset(
Darin Petkovc5f56562011-08-06 16:40:05 -0700237 ProxyFactory::factory()->CreateModemProxy(this, dbus_path_, dbus_owner_));
Darin Petkovbec79a22011-08-01 14:47:17 -0700238 simple_proxy_.reset(
239 ProxyFactory::factory()->CreateModemSimpleProxy(
240 dbus_path_, dbus_owner_));
241 switch (type_) {
242 case kTypeGSM:
243 NOTIMPLEMENTED();
244 break;
245 case kTypeCDMA:
246 cdma_proxy_.reset(
247 ProxyFactory::factory()->CreateModemCDMAProxy(
Darin Petkovd9661952011-08-03 16:25:42 -0700248 this, dbus_path_, dbus_owner_));
Darin Petkovbec79a22011-08-01 14:47:17 -0700249 break;
250 default: NOTREACHED();
251 }
252}
253
Darin Petkovf5f61e02011-07-29 11:35:40 -0700254void Cellular::EnableModem() {
255 CHECK_EQ(kStateDisabled, state_);
256 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
257 proxy_->Enable(true);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700258 SetState(kStateEnabled);
Darin Petkovf5f61e02011-07-29 11:35:40 -0700259}
260
261void Cellular::GetModemStatus() {
Darin Petkovceb68172011-07-29 14:47:48 -0700262 CHECK_EQ(kStateEnabled, state_);
Darin Petkovf5f61e02011-07-29 11:35:40 -0700263 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
264 DBusPropertiesMap properties = simple_proxy_->GetStatus();
Darin Petkovceb68172011-07-29 14:47:48 -0700265 if (DBusProperties::GetString(properties, "carrier", &carrier_) &&
266 type_ == kTypeCDMA) {
267 // TODO(petkov): Set Cellular.FirmwareImageName and home_provider based on
268 // the carrier.
Darin Petkovf5f61e02011-07-29 11:35:40 -0700269 }
Darin Petkovceb68172011-07-29 14:47:48 -0700270 DBusProperties::GetString(properties, "meid", &meid_);
271 DBusProperties::GetString(properties, "imei", &imei_);
272 if (DBusProperties::GetString(properties, "imsi", &imsi_) &&
273 type_ == kTypeGSM) {
274 // TODO(petkov): Set GSM provider.
275 }
276 DBusProperties::GetString(properties, "esn", &esn_);
277 DBusProperties::GetString(properties, "mdn", &mdn_);
278 DBusProperties::GetString(properties, "min", &min_);
Darin Petkovceb68172011-07-29 14:47:48 -0700279 DBusProperties::GetString(
280 properties, "firmware_revision", &firmware_revision_);
Darin Petkovb27e5442011-08-16 14:36:45 -0700281
Darin Petkovc408e692011-08-17 13:47:15 -0700282 // TODO(petkov): Handle "state".
Darin Petkovb27e5442011-08-16 14:36:45 -0700283
Darin Petkovceb68172011-07-29 14:47:48 -0700284 if (type_ == kTypeCDMA) {
Darin Petkovc408e692011-08-17 13:47:15 -0700285 DBusProperties::GetUint32(
286 properties, "activation_state", &cdma_.activation_state);
Darin Petkovcc044422011-08-17 13:30:06 -0700287 DBusProperties::GetUint16(properties, "prl_version", &cdma_.prl_version);
Darin Petkovcc044422011-08-17 13:30:06 -0700288 // TODO(petkov): For now, get the payment and usage URLs from ModemManager
289 // to match flimflam. In the future, provide a plugin API to get these
290 // directly from the modem driver.
291 DBusProperties::GetString(properties, "payment_url", &cdma_.payment_url);
292 DBusProperties::GetString(properties, "usage_url", &cdma_.usage_url);
Darin Petkovceb68172011-07-29 14:47:48 -0700293 }
294}
295
296void Cellular::GetModemIdentifiers() {
297 // TODO(petkov): Implement this.
298 NOTIMPLEMENTED();
299}
300
301void Cellular::GetGSMProperties() {
302 // TODO(petkov): Implement this.
303 NOTIMPLEMENTED();
304}
305
306void Cellular::RegisterGSMModem() {
307 // TODO(petkov): Invoke ModemManager.Modem.Gsm.Network.Register.
308 NOTIMPLEMENTED();
309}
310
311void Cellular::GetModemInfo() {
312 ModemProxyInterface::Info info = proxy_->GetInfo();
313 manufacturer_ = info._1;
314 model_id_ = info._2;
315 hardware_revision_ = info._3;
316 VLOG(2) << "ModemInfo: " << manufacturer_ << ", " << model_id_ << ", "
317 << hardware_revision_;
318}
319
320void Cellular::GetModemRegistrationState() {
Darin Petkovbec79a22011-08-01 14:47:17 -0700321 switch (type_) {
322 case kTypeGSM:
323 GetGSMRegistrationState();
324 break;
325 case kTypeCDMA:
326 GetCDMARegistrationState();
327 break;
328 default: NOTREACHED();
329 }
Darin Petkovd9661952011-08-03 16:25:42 -0700330 HandleNewRegistrationState();
Darin Petkovbec79a22011-08-01 14:47:17 -0700331}
332
333void Cellular::GetCDMARegistrationState() {
334 CHECK_EQ(kTypeCDMA, type_);
335 cdma_proxy_->GetRegistrationState(&cdma_.registration_state_1x,
336 &cdma_.registration_state_evdo);
337 VLOG(2) << "CDMA Registration: 1x(" << cdma_.registration_state_1x
338 << ") EVDO(" << cdma_.registration_state_evdo << ")";
339 // TODO(petkov): handle_reported_connect?
340}
341
342void Cellular::GetGSMRegistrationState() {
Darin Petkovceb68172011-07-29 14:47:48 -0700343 // TODO(petkov): Implement this.
344 NOTIMPLEMENTED();
345}
346
Darin Petkovd9661952011-08-03 16:25:42 -0700347bool Cellular::IsModemRegistered() {
348 return cdma_.registration_state_1x !=
349 MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN ||
350 cdma_.registration_state_evdo !=
351 MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN;
352 // TODO(petkov): Handle GSM states.
353}
354
355void Cellular::HandleNewRegistrationState() {
Darin Petkov0828f5f2011-08-11 10:18:52 -0700356 dispatcher_->PostTask(
357 task_factory_.NewRunnableMethod(
358 &Cellular::HandleNewRegistrationStateTask));
359}
360
361void Cellular::HandleNewRegistrationStateTask() {
Darin Petkovd9661952011-08-03 16:25:42 -0700362 VLOG(2) << __func__;
363 if (!IsModemRegistered()) {
Darin Petkovc408e692011-08-17 13:47:15 -0700364 if (state_ == kStateLinked) {
365 manager_->DeregisterService(service_);
366 }
Darin Petkovd9661952011-08-03 16:25:42 -0700367 service_ = NULL;
Darin Petkov0828f5f2011-08-11 10:18:52 -0700368 if (state_ == kStateLinked ||
369 state_ == kStateConnected ||
370 state_ == kStateRegistered) {
371 SetState(kStateEnabled);
Darin Petkovd9661952011-08-03 16:25:42 -0700372 }
373 return;
374 }
Darin Petkovd9661952011-08-03 16:25:42 -0700375 if (state_ == kStateEnabled) {
Darin Petkov0828f5f2011-08-11 10:18:52 -0700376 SetState(kStateRegistered);
Darin Petkovd9661952011-08-03 16:25:42 -0700377 }
378 if (!service_.get()) {
379 // For now, no endpoint is created. Revisit if necessary.
380 CreateService();
381 }
382 GetModemSignalQuality();
Darin Petkov0828f5f2011-08-11 10:18:52 -0700383 if (state_ == kStateRegistered && modem_state_ == kModemStateConnected) {
384 SetState(kStateConnected);
385 EstablishLink();
386 }
Darin Petkovd9661952011-08-03 16:25:42 -0700387 // TODO(petkov): Update the service.
388}
389
390void Cellular::GetModemSignalQuality() {
Darin Petkov0828f5f2011-08-11 10:18:52 -0700391 VLOG(2) << __func__;
Darin Petkovd9661952011-08-03 16:25:42 -0700392 uint32 strength = 0;
393 switch (type_) {
394 case kTypeGSM:
395 strength = GetGSMSignalQuality();
396 break;
397 case kTypeCDMA:
398 strength = GetCDMASignalQuality();
399 break;
400 default: NOTREACHED();
401 }
402 HandleNewSignalQuality(strength);
403}
404
405uint32 Cellular::GetCDMASignalQuality() {
Darin Petkov0828f5f2011-08-11 10:18:52 -0700406 VLOG(2) << __func__;
Darin Petkovd9661952011-08-03 16:25:42 -0700407 CHECK_EQ(kTypeCDMA, type_);
408 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
409 return cdma_proxy_->GetSignalQuality();
410}
411
412uint32 Cellular::GetGSMSignalQuality() {
Darin Petkovceb68172011-07-29 14:47:48 -0700413 // TODO(petkov): Implement this.
414 NOTIMPLEMENTED();
Darin Petkovd9661952011-08-03 16:25:42 -0700415 return 0;
416}
417
418void Cellular::HandleNewSignalQuality(uint32 strength) {
419 VLOG(2) << "Signal strength: " << strength;
420 if (service_.get()) {
421 service_->set_strength(strength);
422 }
423}
424
425void Cellular::CreateService() {
Darin Petkov0828f5f2011-08-11 10:18:52 -0700426 VLOG(2) << __func__;
Darin Petkovd9661952011-08-03 16:25:42 -0700427 CHECK(!service_.get());
428 service_ =
429 new CellularService(control_interface_, dispatcher_, manager_, this);
Darin Petkovc408e692011-08-17 13:47:15 -0700430 switch (type_) {
431 case kTypeGSM:
432 service_->set_activation_state(kActivationStateActivated);
433 break;
434 case kTypeCDMA:
435 service_->set_payment_url(cdma_.payment_url);
436 service_->set_usage_url(cdma_.usage_url);
437 HandleNewCDMAActivationState(MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR);
438 break;
439 default:
440 NOTREACHED();
Darin Petkovcc044422011-08-17 13:30:06 -0700441 }
Darin Petkovd9661952011-08-03 16:25:42 -0700442 // TODO(petkov): Set operator.
Darin Petkovf5f61e02011-07-29 11:35:40 -0700443}
444
Darin Petkov6f9eaa32011-08-09 15:26:44 -0700445bool Cellular::TechnologyIs(const Device::Technology type) const {
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700446 return type == Device::kCellular;
447}
448
Darin Petkovc5f56562011-08-06 16:40:05 -0700449void Cellular::Connect() {
450 VLOG(2) << __func__;
Darin Petkov0828f5f2011-08-11 10:18:52 -0700451 if (state_ == kStateConnected ||
452 state_ == kStateLinked) {
Darin Petkovc5f56562011-08-06 16:40:05 -0700453 return;
454 }
455 CHECK_EQ(kStateRegistered, state_);
456 DBusPropertiesMap properties;
457 const char *phone_number = NULL;
458 switch (type_) {
459 case kTypeGSM:
460 phone_number = kPhoneNumberGSM;
461 break;
462 case kTypeCDMA:
463 phone_number = kPhoneNumberCDMA;
464 break;
465 default: NOTREACHED();
466 }
467 properties[kConnectPropertyPhoneNumber].writer().append_string(phone_number);
468 // TODO(petkov): Setup apn and "home_only".
469
470 // Defer connect because we may be in a dbus-c++ callback.
471 dispatcher_->PostTask(
472 task_factory_.NewRunnableMethod(&Cellular::ConnectTask, properties));
473}
474
475void Cellular::ConnectTask(const DBusPropertiesMap &properties) {
476 VLOG(2) << __func__;
Darin Petkovbac96002011-08-09 13:22:00 -0700477 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Darin Petkovc5f56562011-08-06 16:40:05 -0700478 simple_proxy_->Connect(properties);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700479 SetState(kStateConnected);
Darin Petkovbac96002011-08-09 13:22:00 -0700480 EstablishLink();
481}
482
483void Cellular::EstablishLink() {
484 VLOG(2) << __func__;
Darin Petkov0828f5f2011-08-11 10:18:52 -0700485 CHECK_EQ(kStateConnected, state_);
486 unsigned int flags = 0;
487 if (manager_->device_info()->GetFlags(interface_index_, &flags) &&
488 (flags & IFF_UP) != 0) {
489 LinkEvent(flags, IFF_UP);
490 return;
491 }
492 // TODO(petkov): Provide a timeout for a failed link-up request.
493 RTNLHandler::GetInstance()->SetInterfaceFlags(
494 interface_index_, IFF_UP, IFF_UP);
495}
496
497void Cellular::LinkEvent(unsigned int flags, unsigned int change) {
498 Device::LinkEvent(flags, change);
499 if ((flags & IFF_UP) != 0 && state_ == kStateConnected) {
500 LOG(INFO) << link_name_ << " is up.";
501 SetState(kStateLinked);
502 manager_->RegisterService(service_);
503 // TODO(petkov): For GSM, remember the APN.
Darin Petkov77cb6812011-08-15 16:19:41 -0700504 LOG_IF(ERROR, !AcquireDHCPConfig()) << "Unable to acquire DHCP config.";
Darin Petkov0828f5f2011-08-11 10:18:52 -0700505 } else if ((flags & IFF_UP) == 0 && state_ == kStateLinked) {
506 SetState(kStateConnected);
507 manager_->DeregisterService(service_);
Darin Petkov77cb6812011-08-15 16:19:41 -0700508 DestroyIPConfig();
Darin Petkov0828f5f2011-08-11 10:18:52 -0700509 }
Darin Petkovc5f56562011-08-06 16:40:05 -0700510}
511
Darin Petkovc408e692011-08-17 13:47:15 -0700512void Cellular::Activate(const string &carrier) {
513 CHECK_EQ(kTypeCDMA, type_);
514 // Defer connect because we may be in a dbus-c++ callback.
515 dispatcher_->PostTask(
516 task_factory_.NewRunnableMethod(&Cellular::ActivateTask, carrier));
517}
518
519void Cellular::ActivateTask(const string &carrier) {
520 VLOG(2) << __func__ << "(" << carrier << ")";
521 if (state_ != kStateEnabled && state_ != kStateRegistered) {
522 LOG(ERROR) << "Unable to activate in " << GetStateString(state_);
523 return;
524 }
525 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
526 uint32 status = cdma_proxy_->Activate(carrier);
527 if (status == MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR) {
528 cdma_.activation_state = MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING;
529 }
530 HandleNewCDMAActivationState(status);
531}
532
533void Cellular::HandleNewCDMAActivationState(uint32 error) {
534 if (!service_.get()) {
535 return;
536 }
537 service_->set_activation_state(
538 GetCDMAActivationStateString(cdma_.activation_state));
539 // TODO(petkov): Handle activation state error codes.
540}
541
Darin Petkovb27e5442011-08-16 14:36:45 -0700542void Cellular::OnCDMAActivationStateChanged(
543 uint32 activation_state,
544 uint32 activation_error,
545 const DBusPropertiesMap &status_changes) {
546 CHECK_EQ(kTypeCDMA, type_);
547 DBusProperties::GetString(status_changes, "mdn", &mdn_);
548 DBusProperties::GetString(status_changes, "min", &min_);
Darin Petkovcc044422011-08-17 13:30:06 -0700549 if (DBusProperties::GetString(
550 status_changes, "payment_url", &cdma_.payment_url) &&
Darin Petkovb27e5442011-08-16 14:36:45 -0700551 service_.get()) {
Darin Petkovcc044422011-08-17 13:30:06 -0700552 service_->set_payment_url(cdma_.payment_url);
Darin Petkovb27e5442011-08-16 14:36:45 -0700553 }
Darin Petkovc408e692011-08-17 13:47:15 -0700554 cdma_.activation_state = activation_state;
555 HandleNewCDMAActivationState(activation_error);
Darin Petkovb27e5442011-08-16 14:36:45 -0700556}
557
Darin Petkovd9661952011-08-03 16:25:42 -0700558void Cellular::OnCDMARegistrationStateChanged(uint32 state_1x,
559 uint32 state_evdo) {
560 CHECK_EQ(kTypeCDMA, type_);
561 cdma_.registration_state_1x = state_1x;
562 cdma_.registration_state_evdo = state_evdo;
563 HandleNewRegistrationState();
564}
565
566void Cellular::OnCDMASignalQualityChanged(uint32 strength) {
567 CHECK_EQ(kTypeCDMA, type_);
568 HandleNewSignalQuality(strength);
569}
570
Darin Petkovc5f56562011-08-06 16:40:05 -0700571void Cellular::OnModemStateChanged(uint32 old_state,
572 uint32 new_state,
573 uint32 reason) {
574 // TODO(petkov): Implement this.
575 NOTIMPLEMENTED();
576}
577
Chris Masone889666b2011-07-03 12:58:50 -0700578Stringmaps Cellular::EnumerateNetworks() {
579 Stringmaps to_return;
580 for (vector<Network>::const_iterator it = found_networks_.begin();
581 it != found_networks_.end();
582 ++it) {
583 to_return.push_back(it->ToDict());
584 }
585 return to_return;
586}
587
588StrIntPair Cellular::SimLockStatusToProperty() {
589 return StrIntPair(make_pair(flimflam::kSIMLockTypeProperty,
590 sim_lock_status_.lock_type),
591 make_pair(flimflam::kSIMLockRetriesLeftProperty,
592 sim_lock_status_.retries_left));
593}
594
595void Cellular::HelpRegisterDerivedStringmaps(
596 const string &name,
597 Stringmaps(Cellular::*get)(void),
598 bool(Cellular::*set)(const Stringmaps&)) {
599 store_.RegisterDerivedStringmaps(
600 name,
601 StringmapsAccessor(
602 new CustomAccessor<Cellular, Stringmaps>(this, get, set)));
603}
604
605void Cellular::HelpRegisterDerivedStrIntPair(
606 const string &name,
607 StrIntPair(Cellular::*get)(void),
608 bool(Cellular::*set)(const StrIntPair&)) {
609 store_.RegisterDerivedStrIntPair(
610 name,
611 StrIntPairAccessor(
612 new CustomAccessor<Cellular, StrIntPair>(this, get, set)));
613}
614
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700615} // namespace shill