blob: d92d6e1f5d6983e0610524b85e304d58edf4c588 [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 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>
Darin Petkov137884a2011-10-26 18:52:47 +020018#include <mobile_provider.h>
Chris Masone3bd3c8c2011-06-13 08:20:26 -070019
Darin Petkovdaf43862011-10-27 11:37:28 +020020#include "shill/cellular_capability_cdma.h"
21#include "shill/cellular_capability_gsm.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070022#include "shill/cellular_service.h"
23#include "shill/control_interface.h"
24#include "shill/device.h"
25#include "shill/device_info.h"
Darin Petkov4d6d9412011-08-24 13:19:54 -070026#include "shill/error.h"
Paul Stewart26b327e2011-10-19 11:38:09 -070027#include "shill/event_dispatcher.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070028#include "shill/manager.h"
Darin Petkove604f702011-07-28 15:51:17 -070029#include "shill/modem_simple_proxy_interface.h"
Chris Masone7aa5f902011-07-11 11:13:35 -070030#include "shill/profile.h"
Chris Masone889666b2011-07-03 12:58:50 -070031#include "shill/property_accessor.h"
Darin Petkove9d12e02011-07-27 15:09:37 -070032#include "shill/proxy_factory.h"
Darin Petkov0828f5f2011-08-11 10:18:52 -070033#include "shill/rtnl_handler.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070034
Chris Masone889666b2011-07-03 12:58:50 -070035using std::make_pair;
Darin Petkovc0865312011-09-16 15:31:20 -070036using std::map;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070037using std::string;
Chris Masone889666b2011-07-03 12:58:50 -070038using std::vector;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070039
40namespace shill {
41
Darin Petkovc5f56562011-08-06 16:40:05 -070042const char Cellular::kConnectPropertyPhoneNumber[] = "number";
Darin Petkovc5f56562011-08-06 16:40:05 -070043
Darin Petkov3335b372011-08-22 11:05:32 -070044Cellular::Operator::Operator() {
45 SetName("");
46 SetCode("");
47 SetCountry("");
48}
49
50Cellular::Operator::~Operator() {}
51
52void Cellular::Operator::CopyFrom(const Operator &oper) {
53 dict_ = oper.dict_;
54}
55
56const string &Cellular::Operator::GetName() const {
57 return dict_.find(flimflam::kOperatorNameKey)->second;
58}
59
60void Cellular::Operator::SetName(const string &name) {
61 dict_[flimflam::kOperatorNameKey] = name;
62}
63
64const string &Cellular::Operator::GetCode() const {
65 return dict_.find(flimflam::kOperatorCodeKey)->second;
66}
67
68void Cellular::Operator::SetCode(const string &code) {
69 dict_[flimflam::kOperatorCodeKey] = code;
70}
71
72const string &Cellular::Operator::GetCountry() const {
73 return dict_.find(flimflam::kOperatorCountryKey)->second;
74}
75
76void Cellular::Operator::SetCountry(const string &country) {
77 dict_[flimflam::kOperatorCountryKey] = country;
78}
79
80const Stringmap &Cellular::Operator::ToDict() const {
81 return dict_;
82}
83
Chris Masone3bd3c8c2011-06-13 08:20:26 -070084Cellular::Cellular(ControlInterface *control_interface,
85 EventDispatcher *dispatcher,
86 Manager *manager,
Darin Petkove9d12e02011-07-27 15:09:37 -070087 const string &link_name,
Darin Petkov3335b372011-08-22 11:05:32 -070088 const string &address,
Darin Petkove9d12e02011-07-27 15:09:37 -070089 int interface_index,
90 Type type,
91 const string &owner,
Darin Petkov137884a2011-10-26 18:52:47 +020092 const string &path,
93 mobile_provider_db *provider_db)
Chris Masone3bd3c8c2011-06-13 08:20:26 -070094 : Device(control_interface,
95 dispatcher,
96 manager,
Darin Petkove9d12e02011-07-27 15:09:37 -070097 link_name,
Chris Masone626719f2011-08-18 16:58:48 -070098 address,
Chris Masone3bd3c8c2011-06-13 08:20:26 -070099 interface_index),
Darin Petkovab565bb2011-10-06 02:55:51 -0700100 proxy_factory_(ProxyFactory::GetInstance()),
Darin Petkove9d12e02011-07-27 15:09:37 -0700101 type_(type),
102 state_(kStateDisabled),
Darin Petkovbac96002011-08-09 13:22:00 -0700103 modem_state_(kModemStateUnknown),
Darin Petkove9d12e02011-07-27 15:09:37 -0700104 dbus_owner_(owner),
105 dbus_path_(path),
Darin Petkov137884a2011-10-26 18:52:47 +0200106 provider_db_(provider_db),
Darin Petkovc5f56562011-08-06 16:40:05 -0700107 task_factory_(this),
Darin Petkov1272a432011-11-10 15:53:37 +0100108 allow_roaming_(false) {
mukesh agrawalde29fa82011-09-16 16:16:36 -0700109 PropertyStore *store = this->mutable_store();
Paul Stewartac4ac002011-08-26 12:04:26 -0700110 store->RegisterConstString(flimflam::kCarrierProperty, &carrier_);
111 store->RegisterConstString(flimflam::kDBusConnectionProperty, &dbus_owner_);
112 store->RegisterConstString(flimflam::kDBusObjectProperty, &dbus_path_);
113 store->RegisterBool(flimflam::kCellularAllowRoamingProperty, &allow_roaming_);
114 store->RegisterConstString(flimflam::kEsnProperty, &esn_);
115 store->RegisterConstString(flimflam::kFirmwareRevisionProperty,
Chris Masone27c4aa52011-07-02 13:10:14 -0700116 &firmware_revision_);
Paul Stewartac4ac002011-08-26 12:04:26 -0700117 store->RegisterConstString(flimflam::kHardwareRevisionProperty,
Chris Masone27c4aa52011-07-02 13:10:14 -0700118 &hardware_revision_);
Paul Stewartac4ac002011-08-26 12:04:26 -0700119 store->RegisterConstStringmap(flimflam::kHomeProviderProperty,
Darin Petkov3335b372011-08-22 11:05:32 -0700120 &home_provider_.ToDict());
Paul Stewartac4ac002011-08-26 12:04:26 -0700121 store->RegisterConstString(flimflam::kImeiProperty, &imei_);
122 store->RegisterConstString(flimflam::kImsiProperty, &imsi_);
123 store->RegisterConstString(flimflam::kManufacturerProperty, &manufacturer_);
124 store->RegisterConstString(flimflam::kMdnProperty, &mdn_);
125 store->RegisterConstString(flimflam::kMeidProperty, &meid_);
126 store->RegisterConstString(flimflam::kMinProperty, &min_);
127 store->RegisterConstString(flimflam::kModelIDProperty, &model_id_);
Chris Masoneb925cc82011-06-22 15:39:57 -0700128
Chris Masone889666b2011-07-03 12:58:50 -0700129 HelpRegisterDerivedStrIntPair(flimflam::kSIMLockStatusProperty,
130 &Cellular::SimLockStatusToProperty,
131 NULL);
Chris Masoneb925cc82011-06-22 15:39:57 -0700132
Paul Stewartac4ac002011-08-26 12:04:26 -0700133 VLOG(2) << "Cellular device " << this->link_name() << " initialized: "
Darin Petkove9d12e02011-07-27 15:09:37 -0700134 << GetTypeString();
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700135}
136
Darin Petkove9d12e02011-07-27 15:09:37 -0700137Cellular::~Cellular() {}
138
Darin Petkovcc044422011-08-17 13:30:06 -0700139string Cellular::GetTypeString() const {
Darin Petkove9d12e02011-07-27 15:09:37 -0700140 switch (type_) {
141 case kTypeGSM: return "CellularTypeGSM";
142 case kTypeCDMA: return "CellularTypeCDMA";
Darin Petkov0828f5f2011-08-11 10:18:52 -0700143 default: NOTREACHED();
Darin Petkove9d12e02011-07-27 15:09:37 -0700144 }
Darin Petkov0828f5f2011-08-11 10:18:52 -0700145 return StringPrintf("CellularTypeUnknown-%d", type_);
Darin Petkove9d12e02011-07-27 15:09:37 -0700146}
147
Darin Petkovcc044422011-08-17 13:30:06 -0700148// static
149string Cellular::GetStateString(State state) {
150 switch (state) {
Darin Petkove9d12e02011-07-27 15:09:37 -0700151 case kStateDisabled: return "CellularStateDisabled";
152 case kStateEnabled: return "CellularStateEnabled";
153 case kStateRegistered: return "CellularStateRegistered";
154 case kStateConnected: return "CellularStateConnected";
Darin Petkov0828f5f2011-08-11 10:18:52 -0700155 case kStateLinked: return "CellularStateLinked";
156 default: NOTREACHED();
Darin Petkove9d12e02011-07-27 15:09:37 -0700157 }
Darin Petkovcc044422011-08-17 13:30:06 -0700158 return StringPrintf("CellularStateUnknown-%d", state);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700159}
160
161void Cellular::SetState(State state) {
Darin Petkovcc044422011-08-17 13:30:06 -0700162 VLOG(2) << GetStateString(state_) << " -> " << GetStateString(state);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700163 state_ = state;
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700164}
165
166void Cellular::Start() {
Darin Petkovcc044422011-08-17 13:30:06 -0700167 LOG(INFO) << __func__ << ": " << GetStateString(state_);
Darin Petkov3335b372011-08-22 11:05:32 -0700168 Device::Start();
Darin Petkovdaf43862011-10-27 11:37:28 +0200169 InitCapability(); // For now, only a single capability is supported.
Darin Petkovbec79a22011-08-01 14:47:17 -0700170 InitProxies();
Darin Petkovf5f61e02011-07-29 11:35:40 -0700171 EnableModem();
Darin Petkov184c54e2011-11-15 12:44:39 +0100172 capability_->Register();
Darin Petkovf5f61e02011-07-29 11:35:40 -0700173 GetModemStatus();
Darin Petkovcb547732011-11-09 13:55:26 +0100174 capability_->GetIdentifiers();
Darin Petkov184c54e2011-11-15 12:44:39 +0100175 capability_->GetProperties();
Darin Petkovceb68172011-07-29 14:47:48 -0700176 GetModemInfo();
Darin Petkov184c54e2011-11-15 12:44:39 +0100177 capability_->GetRegistrationState();
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700178}
179
180void Cellular::Stop() {
Darin Petkovdaf43862011-10-27 11:37:28 +0200181 capability_.reset();
Darin Petkove9d12e02011-07-27 15:09:37 -0700182 proxy_.reset();
Darin Petkove604f702011-07-28 15:51:17 -0700183 simple_proxy_.reset();
Paul Stewartac4ac002011-08-26 12:04:26 -0700184 manager()->DeregisterService(service_);
Darin Petkove9d12e02011-07-27 15:09:37 -0700185 service_ = NULL; // Breaks a reference cycle.
Darin Petkov0828f5f2011-08-11 10:18:52 -0700186 SetState(kStateDisabled);
Darin Petkov3335b372011-08-22 11:05:32 -0700187 Device::Stop();
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700188}
189
Darin Petkovdaf43862011-10-27 11:37:28 +0200190void Cellular::InitCapability() {
191 VLOG(2) << __func__;
192 switch (type_) {
193 case kTypeGSM:
194 capability_.reset(new CellularCapabilityGSM(this));
195 break;
196 case kTypeCDMA:
197 capability_.reset(new CellularCapabilityCDMA(this));
198 break;
199 default: NOTREACHED();
200 }
201}
202
Darin Petkovbec79a22011-08-01 14:47:17 -0700203void Cellular::InitProxies() {
Darin Petkovcc044422011-08-17 13:30:06 -0700204 VLOG(2) << __func__;
Darin Petkovab565bb2011-10-06 02:55:51 -0700205 proxy_.reset(proxy_factory_->CreateModemProxy(this, dbus_path_, dbus_owner_));
Darin Petkovbec79a22011-08-01 14:47:17 -0700206 simple_proxy_.reset(
Darin Petkovab565bb2011-10-06 02:55:51 -0700207 proxy_factory_->CreateModemSimpleProxy(dbus_path_, dbus_owner_));
Darin Petkovdaf43862011-10-27 11:37:28 +0200208 capability_->InitProxies();
Darin Petkovbec79a22011-08-01 14:47:17 -0700209}
210
Darin Petkovf5f61e02011-07-29 11:35:40 -0700211void Cellular::EnableModem() {
212 CHECK_EQ(kStateDisabled, state_);
213 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
214 proxy_->Enable(true);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700215 SetState(kStateEnabled);
Darin Petkovf5f61e02011-07-29 11:35:40 -0700216}
217
218void Cellular::GetModemStatus() {
Darin Petkovceb68172011-07-29 14:47:48 -0700219 CHECK_EQ(kStateEnabled, state_);
Darin Petkovf5f61e02011-07-29 11:35:40 -0700220 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
221 DBusPropertiesMap properties = simple_proxy_->GetStatus();
Darin Petkovae0c64e2011-11-15 15:50:27 +0100222 DBusProperties::GetString(properties, "carrier", &carrier_);
Darin Petkovceb68172011-07-29 14:47:48 -0700223 DBusProperties::GetString(properties, "meid", &meid_);
224 DBusProperties::GetString(properties, "imei", &imei_);
Darin Petkovae0c64e2011-11-15 15:50:27 +0100225 DBusProperties::GetString(properties, "imsi", &imsi_);
Darin Petkovceb68172011-07-29 14:47:48 -0700226 DBusProperties::GetString(properties, "esn", &esn_);
227 DBusProperties::GetString(properties, "mdn", &mdn_);
228 DBusProperties::GetString(properties, "min", &min_);
Darin Petkovceb68172011-07-29 14:47:48 -0700229 DBusProperties::GetString(
230 properties, "firmware_revision", &firmware_revision_);
Darin Petkovb27e5442011-08-16 14:36:45 -0700231
Darin Petkovd2045802011-08-23 11:09:25 -0700232 uint32 state = 0;
233 if (DBusProperties::GetUint32(properties, "state", &state)) {
234 modem_state_ = static_cast<ModemState>(state);
235 }
Darin Petkovb27e5442011-08-16 14:36:45 -0700236
Darin Petkovae0c64e2011-11-15 15:50:27 +0100237 capability_->UpdateStatus(properties);
Darin Petkovceb68172011-07-29 14:47:48 -0700238}
239
Darin Petkov184c54e2011-11-15 12:44:39 +0100240void Cellular::Activate(const std::string &carrier, Error *error) {
241 capability_->Activate(carrier, error);
Darin Petkov9ae310f2011-08-30 15:41:13 -0700242}
243
244void Cellular::RegisterOnNetwork(const string &network_id, Error *error) {
Darin Petkov184c54e2011-11-15 12:44:39 +0100245 capability_->RegisterOnNetwork(network_id, error);
Darin Petkova3d3be52011-11-14 21:34:16 +0100246}
247
Darin Petkove42e1012011-08-31 12:35:04 -0700248void Cellular::RequirePIN(const string &pin, bool require, Error *error) {
Darin Petkovb05315f2011-11-07 10:14:25 +0100249 capability_->RequirePIN(pin, require, error);
Darin Petkove42e1012011-08-31 12:35:04 -0700250}
251
252void Cellular::EnterPIN(const string &pin, Error *error) {
Darin Petkovb05315f2011-11-07 10:14:25 +0100253 capability_->EnterPIN(pin, error);
Darin Petkove42e1012011-08-31 12:35:04 -0700254}
255
Darin Petkovb05315f2011-11-07 10:14:25 +0100256void Cellular::UnblockPIN(
257 const string &unblock_code, const string &pin, Error *error) {
258 capability_->UnblockPIN(unblock_code, pin, error);
Darin Petkove42e1012011-08-31 12:35:04 -0700259}
260
Darin Petkovb05315f2011-11-07 10:14:25 +0100261void Cellular::ChangePIN(
262 const string &old_pin, const string &new_pin, Error *error) {
263 capability_->ChangePIN(old_pin, new_pin, error);
Darin Petkove42e1012011-08-31 12:35:04 -0700264}
265
Darin Petkov1272a432011-11-10 15:53:37 +0100266void Cellular::Scan(Error *error) {
267 capability_->Scan(error);
268}
269
Darin Petkovceb68172011-07-29 14:47:48 -0700270void Cellular::GetModemInfo() {
Darin Petkovd2045802011-08-23 11:09:25 -0700271 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Darin Petkovceb68172011-07-29 14:47:48 -0700272 ModemProxyInterface::Info info = proxy_->GetInfo();
273 manufacturer_ = info._1;
274 model_id_ = info._2;
275 hardware_revision_ = info._3;
276 VLOG(2) << "ModemInfo: " << manufacturer_ << ", " << model_id_ << ", "
277 << hardware_revision_;
278}
279
Darin Petkovd9661952011-08-03 16:25:42 -0700280void Cellular::HandleNewRegistrationState() {
Paul Stewartac4ac002011-08-26 12:04:26 -0700281 dispatcher()->PostTask(
Darin Petkov0828f5f2011-08-11 10:18:52 -0700282 task_factory_.NewRunnableMethod(
283 &Cellular::HandleNewRegistrationStateTask));
284}
285
286void Cellular::HandleNewRegistrationStateTask() {
Darin Petkovd9661952011-08-03 16:25:42 -0700287 VLOG(2) << __func__;
Darin Petkov20c13ec2011-11-09 15:07:15 +0100288 const string network_tech = capability_->GetNetworkTechnologyString();
Darin Petkovd2045802011-08-23 11:09:25 -0700289 if (network_tech.empty()) {
Darin Petkovc408e692011-08-17 13:47:15 -0700290 if (state_ == kStateLinked) {
Paul Stewartac4ac002011-08-26 12:04:26 -0700291 manager()->DeregisterService(service_);
Darin Petkovc408e692011-08-17 13:47:15 -0700292 }
Darin Petkovd9661952011-08-03 16:25:42 -0700293 service_ = NULL;
Darin Petkov0828f5f2011-08-11 10:18:52 -0700294 if (state_ == kStateLinked ||
295 state_ == kStateConnected ||
296 state_ == kStateRegistered) {
297 SetState(kStateEnabled);
Darin Petkovd9661952011-08-03 16:25:42 -0700298 }
299 return;
300 }
Darin Petkovd9661952011-08-03 16:25:42 -0700301 if (state_ == kStateEnabled) {
Darin Petkov0828f5f2011-08-11 10:18:52 -0700302 SetState(kStateRegistered);
Darin Petkovd9661952011-08-03 16:25:42 -0700303 }
304 if (!service_.get()) {
305 // For now, no endpoint is created. Revisit if necessary.
306 CreateService();
307 }
Darin Petkov3e509242011-11-10 14:46:44 +0100308 capability_->GetSignalQuality();
Darin Petkov0828f5f2011-08-11 10:18:52 -0700309 if (state_ == kStateRegistered && modem_state_ == kModemStateConnected) {
310 SetState(kStateConnected);
311 EstablishLink();
312 }
Darin Petkovd2045802011-08-23 11:09:25 -0700313 service_->set_network_tech(network_tech);
Darin Petkov20c13ec2011-11-09 15:07:15 +0100314 service_->set_roaming_state(capability_->GetRoamingStateString());
Darin Petkovd9661952011-08-03 16:25:42 -0700315}
316
Darin Petkovd9661952011-08-03 16:25:42 -0700317void Cellular::HandleNewSignalQuality(uint32 strength) {
318 VLOG(2) << "Signal strength: " << strength;
319 if (service_.get()) {
320 service_->set_strength(strength);
321 }
322}
323
324void Cellular::CreateService() {
Darin Petkov0828f5f2011-08-11 10:18:52 -0700325 VLOG(2) << __func__;
Darin Petkovd9661952011-08-03 16:25:42 -0700326 CHECK(!service_.get());
327 service_ =
Paul Stewartac4ac002011-08-26 12:04:26 -0700328 new CellularService(control_interface(), dispatcher(), manager(), this);
Darin Petkovae0c64e2011-11-15 15:50:27 +0100329 capability_->OnServiceCreated();
Darin Petkovf5f61e02011-07-29 11:35:40 -0700330}
331
Paul Stewartfdd16072011-09-16 12:41:35 -0700332bool Cellular::TechnologyIs(const Technology::Identifier type) const {
333 return type == Technology::kCellular;
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700334}
335
Darin Petkov4d6d9412011-08-24 13:19:54 -0700336void Cellular::Connect(Error *error) {
Darin Petkovc5f56562011-08-06 16:40:05 -0700337 VLOG(2) << __func__;
Darin Petkov0828f5f2011-08-11 10:18:52 -0700338 if (state_ == kStateConnected ||
339 state_ == kStateLinked) {
Paul Stewartbe005172011-11-02 18:10:29 -0700340 Error::PopulateAndLog(error, Error::kAlreadyConnected,
341 "Already connected; connection request ignored.");
Darin Petkovc5f56562011-08-06 16:40:05 -0700342 return;
343 }
344 CHECK_EQ(kStateRegistered, state_);
Darin Petkovd2045802011-08-23 11:09:25 -0700345
346 if (!allow_roaming_ &&
347 service_->roaming_state() == flimflam::kRoamingStateRoaming) {
Paul Stewartbe005172011-11-02 18:10:29 -0700348 Error::PopulateAndLog(error, Error::kNotOnHomeNetwork,
349 "Roaming disallowed; connection request ignored.");
Darin Petkov4d6d9412011-08-24 13:19:54 -0700350 CHECK(error);
Darin Petkovd2045802011-08-23 11:09:25 -0700351 return;
352 }
353
Darin Petkovc5f56562011-08-06 16:40:05 -0700354 DBusPropertiesMap properties;
Darin Petkovae0c64e2011-11-15 15:50:27 +0100355 capability_->SetupConnectProperties(&properties);
Darin Petkovc5f56562011-08-06 16:40:05 -0700356
357 // Defer connect because we may be in a dbus-c++ callback.
Paul Stewartac4ac002011-08-26 12:04:26 -0700358 dispatcher()->PostTask(
Darin Petkovc5f56562011-08-06 16:40:05 -0700359 task_factory_.NewRunnableMethod(&Cellular::ConnectTask, properties));
360}
361
362void Cellular::ConnectTask(const DBusPropertiesMap &properties) {
363 VLOG(2) << __func__;
Darin Petkovbac96002011-08-09 13:22:00 -0700364 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Darin Petkovc5f56562011-08-06 16:40:05 -0700365 simple_proxy_->Connect(properties);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700366 SetState(kStateConnected);
Darin Petkovbac96002011-08-09 13:22:00 -0700367 EstablishLink();
368}
369
370void Cellular::EstablishLink() {
371 VLOG(2) << __func__;
Darin Petkov0828f5f2011-08-11 10:18:52 -0700372 CHECK_EQ(kStateConnected, state_);
373 unsigned int flags = 0;
Paul Stewartac4ac002011-08-26 12:04:26 -0700374 if (manager()->device_info()->GetFlags(interface_index(), &flags) &&
Darin Petkov0828f5f2011-08-11 10:18:52 -0700375 (flags & IFF_UP) != 0) {
376 LinkEvent(flags, IFF_UP);
377 return;
378 }
379 // TODO(petkov): Provide a timeout for a failed link-up request.
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700380 rtnl_handler()->SetInterfaceFlags(interface_index(), IFF_UP, IFF_UP);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700381}
382
383void Cellular::LinkEvent(unsigned int flags, unsigned int change) {
384 Device::LinkEvent(flags, change);
385 if ((flags & IFF_UP) != 0 && state_ == kStateConnected) {
Paul Stewartac4ac002011-08-26 12:04:26 -0700386 LOG(INFO) << link_name() << " is up.";
Darin Petkov0828f5f2011-08-11 10:18:52 -0700387 SetState(kStateLinked);
Paul Stewartac4ac002011-08-26 12:04:26 -0700388 manager()->RegisterService(service_);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700389 // TODO(petkov): For GSM, remember the APN.
Darin Petkov60b8c3b2011-08-25 11:03:20 -0700390 if (AcquireDHCPConfig()) {
391 SelectService(service_);
392 SetServiceState(Service::kStateConfiguring);
393 } else {
394 LOG(ERROR) << "Unable to acquire DHCP config.";
395 }
Darin Petkov0828f5f2011-08-11 10:18:52 -0700396 } else if ((flags & IFF_UP) == 0 && state_ == kStateLinked) {
397 SetState(kStateConnected);
Paul Stewartac4ac002011-08-26 12:04:26 -0700398 manager()->DeregisterService(service_);
Darin Petkov60b8c3b2011-08-25 11:03:20 -0700399 SelectService(NULL);
Darin Petkov77cb6812011-08-15 16:19:41 -0700400 DestroyIPConfig();
Darin Petkov0828f5f2011-08-11 10:18:52 -0700401 }
Darin Petkovc5f56562011-08-06 16:40:05 -0700402}
403
mukesh agrawal1830fa12011-09-26 14:31:40 -0700404void Cellular::OnModemStateChanged(uint32 /*old_state*/,
405 uint32 /*new_state*/,
406 uint32 /*reason*/) {
Darin Petkovc5f56562011-08-06 16:40:05 -0700407 // TODO(petkov): Implement this.
408 NOTIMPLEMENTED();
409}
410
Darin Petkovae0c64e2011-11-15 15:50:27 +0100411void Cellular::OnModemManagerPropertiesChanged(
412 const DBusPropertiesMap &properties) {
413 if (capability_.get()) {
414 capability_->OnModemManagerPropertiesChanged(properties);
Darin Petkov137884a2011-10-26 18:52:47 +0200415 }
416}
417
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800418StrIntPair Cellular::SimLockStatusToProperty(Error */*error*/) {
Chris Masone889666b2011-07-03 12:58:50 -0700419 return StrIntPair(make_pair(flimflam::kSIMLockTypeProperty,
420 sim_lock_status_.lock_type),
421 make_pair(flimflam::kSIMLockRetriesLeftProperty,
422 sim_lock_status_.retries_left));
423}
424
Darin Petkovae0c64e2011-11-15 15:50:27 +0100425void Cellular::set_home_provider(const Operator &oper) {
426 home_provider_.CopyFrom(oper);
427}
428
Chris Masone889666b2011-07-03 12:58:50 -0700429void Cellular::HelpRegisterDerivedStrIntPair(
430 const string &name,
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800431 StrIntPair(Cellular::*get)(Error *),
mukesh agrawalffa3d042011-10-06 15:26:10 -0700432 void(Cellular::*set)(const StrIntPair&, Error *)) {
mukesh agrawalde29fa82011-09-16 16:16:36 -0700433 mutable_store()->RegisterDerivedStrIntPair(
Chris Masone889666b2011-07-03 12:58:50 -0700434 name,
435 StrIntPairAccessor(
436 new CustomAccessor<Cellular, StrIntPair>(this, get, set)));
437}
438
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700439} // namespace shill