blob: 94ad6720a39eb88f2c29d71617dc5335703c5ed5 [file] [log] [blame]
Darin Petkovc64fe5e2012-01-11 12:46:13 +01001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Chris Masone3bd3c8c2011-06-13 08:20:26 -07002// 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
Eric Shienbrood3e20a232012-02-16 11:35:56 -050014#include <base/bind.h>
Chris Masone3bd3c8c2011-06-13 08:20:26 -070015#include <base/logging.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 Petkov137884a2011-10-26 18:52:47 +020018#include <mobile_provider.h>
Chris Masone3bd3c8c2011-06-13 08:20:26 -070019
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050020#include "shill/adaptor_interfaces.h"
Darin Petkovdaf43862011-10-27 11:37:28 +020021#include "shill/cellular_capability_cdma.h"
22#include "shill/cellular_capability_gsm.h"
Jason Glasgow82f9ab32012-04-04 14:27:19 -040023#include "shill/cellular_capability_universal.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070024#include "shill/cellular_service.h"
25#include "shill/control_interface.h"
26#include "shill/device.h"
27#include "shill/device_info.h"
Darin Petkov4d6d9412011-08-24 13:19:54 -070028#include "shill/error.h"
Paul Stewart26b327e2011-10-19 11:38:09 -070029#include "shill/event_dispatcher.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070030#include "shill/manager.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"
Gaurav Shah435de2c2011-11-17 19:01:07 -080035#include "shill/technology.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070036
Eric Shienbrood3e20a232012-02-16 11:35:56 -050037using base::Bind;
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 Petkov3335b372011-08-22 11:05:32 -070043Cellular::Operator::Operator() {
44 SetName("");
45 SetCode("");
46 SetCountry("");
47}
48
49Cellular::Operator::~Operator() {}
50
51void Cellular::Operator::CopyFrom(const Operator &oper) {
52 dict_ = oper.dict_;
53}
54
55const string &Cellular::Operator::GetName() const {
56 return dict_.find(flimflam::kOperatorNameKey)->second;
57}
58
59void Cellular::Operator::SetName(const string &name) {
60 dict_[flimflam::kOperatorNameKey] = name;
61}
62
63const string &Cellular::Operator::GetCode() const {
64 return dict_.find(flimflam::kOperatorCodeKey)->second;
65}
66
67void Cellular::Operator::SetCode(const string &code) {
68 dict_[flimflam::kOperatorCodeKey] = code;
69}
70
71const string &Cellular::Operator::GetCountry() const {
72 return dict_.find(flimflam::kOperatorCountryKey)->second;
73}
74
75void Cellular::Operator::SetCountry(const string &country) {
76 dict_[flimflam::kOperatorCountryKey] = country;
77}
78
79const Stringmap &Cellular::Operator::ToDict() const {
80 return dict_;
81}
82
Chris Masone3bd3c8c2011-06-13 08:20:26 -070083Cellular::Cellular(ControlInterface *control_interface,
84 EventDispatcher *dispatcher,
Thieu Le3426c8f2012-01-11 17:35:11 -080085 Metrics *metrics,
Chris Masone3bd3c8c2011-06-13 08:20:26 -070086 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,
Thieu Le3426c8f2012-01-11 17:35:11 -080096 metrics,
Chris Masone3bd3c8c2011-06-13 08:20:26 -070097 manager,
Darin Petkove9d12e02011-07-27 15:09:37 -070098 link_name,
Chris Masone626719f2011-08-18 16:58:48 -070099 address,
Gaurav Shah435de2c2011-11-17 19:01:07 -0800100 interface_index,
101 Technology::kCellular),
Darin Petkove9d12e02011-07-27 15:09:37 -0700102 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),
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500106 provider_db_(provider_db) {
mukesh agrawalde29fa82011-09-16 16:16:36 -0700107 PropertyStore *store = this->mutable_store();
Paul Stewartac4ac002011-08-26 12:04:26 -0700108 store->RegisterConstString(flimflam::kDBusConnectionProperty, &dbus_owner_);
109 store->RegisterConstString(flimflam::kDBusObjectProperty, &dbus_path_);
Eric Shienbrood0db6a9b2012-03-30 16:11:39 -0400110 HelpRegisterDerivedString(flimflam::kTechnologyFamilyProperty,
111 &Cellular::GetTechnologyFamily,
112 NULL);
Paul Stewartac4ac002011-08-26 12:04:26 -0700113 store->RegisterConstStringmap(flimflam::kHomeProviderProperty,
Darin Petkov3335b372011-08-22 11:05:32 -0700114 &home_provider_.ToDict());
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500115 // For now, only a single capability is supported.
116 InitCapability(type, ProxyFactory::GetInstance());
Chris Masoneb925cc82011-06-22 15:39:57 -0700117
Darin Petkov5f316f62011-11-18 12:10:26 +0100118 VLOG(2) << "Cellular device " << this->link_name() << " initialized.";
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700119}
120
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500121Cellular::~Cellular() {
122}
Darin Petkove9d12e02011-07-27 15:09:37 -0700123
Darin Petkovcc044422011-08-17 13:30:06 -0700124// static
125string Cellular::GetStateString(State state) {
126 switch (state) {
Darin Petkove9d12e02011-07-27 15:09:37 -0700127 case kStateDisabled: return "CellularStateDisabled";
128 case kStateEnabled: return "CellularStateEnabled";
129 case kStateRegistered: return "CellularStateRegistered";
130 case kStateConnected: return "CellularStateConnected";
Darin Petkov0828f5f2011-08-11 10:18:52 -0700131 case kStateLinked: return "CellularStateLinked";
132 default: NOTREACHED();
Darin Petkove9d12e02011-07-27 15:09:37 -0700133 }
Darin Petkovcc044422011-08-17 13:30:06 -0700134 return StringPrintf("CellularStateUnknown-%d", state);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700135}
136
Eric Shienbrood0db6a9b2012-03-30 16:11:39 -0400137string Cellular::GetTechnologyFamily(Error *error) {
138 return capability_->GetTypeString();
139}
140
Darin Petkov0828f5f2011-08-11 10:18:52 -0700141void Cellular::SetState(State state) {
Darin Petkovcc044422011-08-17 13:30:06 -0700142 VLOG(2) << GetStateString(state_) << " -> " << GetStateString(state);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700143 state_ = state;
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700144}
145
Eric Shienbrood0db6a9b2012-03-30 16:11:39 -0400146void Cellular::HelpRegisterDerivedString(
147 const string &name,
148 string(Cellular::*get)(Error *),
149 void(Cellular::*set)(const string&, Error *)) {
150 mutable_store()->RegisterDerivedString(
151 name,
152 StringAccessor(new CustomAccessor<Cellular, string>(this, get, set)));
153}
154
Eric Shienbrood9a245532012-03-07 14:20:39 -0500155void Cellular::Start(Error *error,
156 const EnabledStateChangedCallback &callback) {
Jason Glasgow4a490792012-04-10 15:02:05 -0400157 DCHECK(error);
Eric Shienbrood9a245532012-03-07 14:20:39 -0500158 VLOG(2) << __func__ << ": " << GetStateString(state_);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500159 if (state_ != kStateDisabled) {
160 return;
161 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500162 if (modem_state_ == kModemStateEnabled) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500163 // Modem already enabled. Make sure shill
164 // state matches ModemManager state.
165 SetState(kStateEnabled);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500166 return;
167 }
Eric Shienbrood9a245532012-03-07 14:20:39 -0500168 capability_->StartModem(error,
169 Bind(&Cellular::OnModemStarted, this, callback));
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700170}
171
Eric Shienbrood9a245532012-03-07 14:20:39 -0500172void Cellular::Stop(Error *error,
173 const EnabledStateChangedCallback &callback) {
174 VLOG(2) << __func__ << ": " << GetStateString(state_);
175 if (service_) {
176 // TODO(ers): See whether we can/should do DestroyService() here.
177 manager()->DeregisterService(service_);
178 service_ = NULL;
179 }
180 capability_->StopModem(error,
181 Bind(&Cellular::OnModemStopped, this, callback));
182}
183
184void Cellular::OnModemStarted(const EnabledStateChangedCallback &callback,
185 const Error &error) {
186 VLOG(2) << __func__ << ": " << GetStateString(state_);
187 if (state_ == kStateDisabled)
188 SetState(kStateEnabled);
189 callback.Run(error);
190}
191
192void Cellular::OnModemStopped(const EnabledStateChangedCallback &callback,
193 const Error &error) {
194 VLOG(2) << __func__ << ": " << GetStateString(state_);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500195 if (state_ != kStateDisabled)
Eric Shienbrood9a245532012-03-07 14:20:39 -0500196 SetState(kStateDisabled);
197 callback.Run(error);
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700198}
199
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500200void Cellular::InitCapability(Type type, ProxyFactory *proxy_factory) {
Darin Petkov5f316f62011-11-18 12:10:26 +0100201 // TODO(petkov): Consider moving capability construction into a factory that's
202 // external to the Cellular class.
203 VLOG(2) << __func__ << "(" << type << ")";
204 switch (type) {
Darin Petkovdaf43862011-10-27 11:37:28 +0200205 case kTypeGSM:
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500206 capability_.reset(new CellularCapabilityGSM(this, proxy_factory));
Darin Petkovdaf43862011-10-27 11:37:28 +0200207 break;
208 case kTypeCDMA:
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500209 capability_.reset(new CellularCapabilityCDMA(this, proxy_factory));
Darin Petkovdaf43862011-10-27 11:37:28 +0200210 break;
David Rochbergfa1d31d2012-03-20 10:38:07 -0400211 case kTypeUniversal:
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400212 capability_.reset(new CellularCapabilityUniversal(this, proxy_factory));
David Rochbergfa1d31d2012-03-20 10:38:07 -0400213 break;
Darin Petkovdaf43862011-10-27 11:37:28 +0200214 default: NOTREACHED();
215 }
216}
217
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400218void Cellular::Activate(const string &carrier,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500219 Error *error, const ResultCallback &callback) {
220 capability_->Activate(carrier, error, callback);
Darin Petkov9ae310f2011-08-30 15:41:13 -0700221}
222
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500223void Cellular::RegisterOnNetwork(const string &network_id,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500224 Error *error,
225 const ResultCallback &callback) {
226 capability_->RegisterOnNetwork(network_id, error, callback);
Darin Petkova3d3be52011-11-14 21:34:16 +0100227}
228
Eric Shienbrood9a245532012-03-07 14:20:39 -0500229void Cellular::RequirePIN(const string &pin, bool require,
230 Error *error, const ResultCallback &callback) {
231 VLOG(2) << __func__ << "(" << require << ")";
232 capability_->RequirePIN(pin, require, error, callback);
Darin Petkove42e1012011-08-31 12:35:04 -0700233}
234
Eric Shienbrood9a245532012-03-07 14:20:39 -0500235void Cellular::EnterPIN(const string &pin,
236 Error *error, const ResultCallback &callback) {
237 VLOG(2) << __func__;
238 capability_->EnterPIN(pin, error, callback);
Darin Petkove42e1012011-08-31 12:35:04 -0700239}
240
Darin Petkovc64fe5e2012-01-11 12:46:13 +0100241void Cellular::UnblockPIN(const string &unblock_code,
242 const string &pin,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500243 Error *error, const ResultCallback &callback) {
244 VLOG(2) << __func__;
245 capability_->UnblockPIN(unblock_code, pin, error, callback);
Darin Petkove42e1012011-08-31 12:35:04 -0700246}
247
Eric Shienbrood9a245532012-03-07 14:20:39 -0500248void Cellular::ChangePIN(const string &old_pin, const string &new_pin,
249 Error *error, const ResultCallback &callback) {
250 VLOG(2) << __func__;
251 capability_->ChangePIN(old_pin, new_pin, error, callback);
Darin Petkove42e1012011-08-31 12:35:04 -0700252}
253
Eric Shienbrood9a245532012-03-07 14:20:39 -0500254void Cellular::Scan(Error *error) {
255 // TODO(ers): for now report immediate success or failure.
256 capability_->Scan(error, ResultCallback());
Darin Petkovceb68172011-07-29 14:47:48 -0700257}
258
Darin Petkovd9661952011-08-03 16:25:42 -0700259void Cellular::HandleNewRegistrationState() {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500260 VLOG(2) << __func__ << ": " << GetStateString(state_);
Darin Petkovb72cf402011-11-22 14:51:39 +0100261 if (!capability_->IsRegistered()) {
Darin Petkov2c377382012-01-11 11:40:43 +0100262 DestroyService();
Darin Petkov0828f5f2011-08-11 10:18:52 -0700263 if (state_ == kStateLinked ||
264 state_ == kStateConnected ||
265 state_ == kStateRegistered) {
266 SetState(kStateEnabled);
Darin Petkovd9661952011-08-03 16:25:42 -0700267 }
268 return;
269 }
Eric Shienbrood9a245532012-03-07 14:20:39 -0500270 // In Disabled state, defer creating a service until fully
271 // enabled. UI will ignore the appearance of a new service
272 // on a disabled device.
273 if (state_ == kStateDisabled) {
274 return;
275 }
Darin Petkovd9661952011-08-03 16:25:42 -0700276 if (state_ == kStateEnabled) {
Darin Petkov0828f5f2011-08-11 10:18:52 -0700277 SetState(kStateRegistered);
Darin Petkovd9661952011-08-03 16:25:42 -0700278 }
279 if (!service_.get()) {
Darin Petkovd9661952011-08-03 16:25:42 -0700280 CreateService();
281 }
Darin Petkov3e509242011-11-10 14:46:44 +0100282 capability_->GetSignalQuality();
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500283 if (state_ == kStateRegistered && modem_state_ == kModemStateConnected)
284 OnConnected();
Darin Petkovb72cf402011-11-22 14:51:39 +0100285 service_->SetNetworkTechnology(capability_->GetNetworkTechnologyString());
286 service_->SetRoamingState(capability_->GetRoamingStateString());
Darin Petkovd9661952011-08-03 16:25:42 -0700287}
288
Darin Petkovd9661952011-08-03 16:25:42 -0700289void Cellular::HandleNewSignalQuality(uint32 strength) {
290 VLOG(2) << "Signal strength: " << strength;
Darin Petkovd78ee7e2012-01-12 11:21:10 +0100291 if (service_) {
292 service_->SetStrength(strength);
Darin Petkovd9661952011-08-03 16:25:42 -0700293 }
294}
295
296void Cellular::CreateService() {
Darin Petkov0828f5f2011-08-11 10:18:52 -0700297 VLOG(2) << __func__;
Darin Petkovd9661952011-08-03 16:25:42 -0700298 CHECK(!service_.get());
299 service_ =
Thieu Le3426c8f2012-01-11 17:35:11 -0800300 new CellularService(control_interface(), dispatcher(), metrics(),
301 manager(), this);
Darin Petkovae0c64e2011-11-15 15:50:27 +0100302 capability_->OnServiceCreated();
Darin Petkov31332412012-01-28 01:50:02 +0100303 manager()->RegisterService(service_);
Darin Petkovf5f61e02011-07-29 11:35:40 -0700304}
305
Darin Petkov2c377382012-01-11 11:40:43 +0100306void Cellular::DestroyService() {
307 VLOG(2) << __func__;
308 DestroyIPConfig();
309 if (service_) {
310 manager()->DeregisterService(service_);
311 service_ = NULL;
312 }
313 SelectService(NULL);
314}
315
Paul Stewartfdd16072011-09-16 12:41:35 -0700316bool Cellular::TechnologyIs(const Technology::Identifier type) const {
317 return type == Technology::kCellular;
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700318}
319
Darin Petkov4d6d9412011-08-24 13:19:54 -0700320void Cellular::Connect(Error *error) {
Darin Petkovc5f56562011-08-06 16:40:05 -0700321 VLOG(2) << __func__;
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400322 if (state_ == kStateConnected || state_ == kStateLinked) {
Paul Stewartbe005172011-11-02 18:10:29 -0700323 Error::PopulateAndLog(error, Error::kAlreadyConnected,
324 "Already connected; connection request ignored.");
Darin Petkovc5f56562011-08-06 16:40:05 -0700325 return;
326 }
327 CHECK_EQ(kStateRegistered, state_);
Darin Petkovd2045802011-08-23 11:09:25 -0700328
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400329 if (!capability_->AllowRoaming() &&
Darin Petkovd2045802011-08-23 11:09:25 -0700330 service_->roaming_state() == flimflam::kRoamingStateRoaming) {
Paul Stewartbe005172011-11-02 18:10:29 -0700331 Error::PopulateAndLog(error, Error::kNotOnHomeNetwork,
332 "Roaming disallowed; connection request ignored.");
Darin Petkovd2045802011-08-23 11:09:25 -0700333 return;
334 }
335
Darin Petkovc5f56562011-08-06 16:40:05 -0700336 DBusPropertiesMap properties;
Darin Petkovae0c64e2011-11-15 15:50:27 +0100337 capability_->SetupConnectProperties(&properties);
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -0400338 service_->SetState(Service::kStateAssociating);
Nathan Williamsb54974f2012-04-19 11:16:30 -0400339 // TODO(njw): Should a weak pointer be used here instead?
340 // Would require something like a WeakPtrFactory on the class,
341 // and the Classic and Universal subclasses already have one.
342 ResultCallback cb = Bind(&Cellular::OnConnectReply, this);
343 capability_->Connect(properties, error, cb);
344}
345
346// Note that there's no ResultCallback argument to this,
347// since Connect() isn't yet passed one.
348void Cellular::OnConnectReply(const Error &error) {
349 VLOG(2) << __func__ << "(" << error << ")";
350 if (error.IsSuccess())
351 OnConnected();
352 else
353 OnConnectFailed(error);
Darin Petkovc5f56562011-08-06 16:40:05 -0700354}
355
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500356void Cellular::OnConnected() {
Darin Petkovc5f56562011-08-06 16:40:05 -0700357 VLOG(2) << __func__;
Darin Petkov0828f5f2011-08-11 10:18:52 -0700358 SetState(kStateConnected);
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400359 if (!capability_->AllowRoaming() &&
Darin Petkov9c1dcef2012-02-07 15:58:26 +0100360 service_->roaming_state() == flimflam::kRoamingStateRoaming) {
361 Disconnect(NULL);
362 } else {
363 EstablishLink();
364 }
Darin Petkovbac96002011-08-09 13:22:00 -0700365}
366
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400367void Cellular::OnConnectFailed(const Error &error) {
368 service()->SetFailure(Service::kFailureUnknown);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500369}
370
Darin Petkovfb0625e2012-01-16 13:05:56 +0100371void Cellular::Disconnect(Error *error) {
372 VLOG(2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500373 if (state_ != kStateConnected && state_ != kStateLinked) {
Darin Petkovfb0625e2012-01-16 13:05:56 +0100374 Error::PopulateAndLog(
Eric Shienbrood9a245532012-03-07 14:20:39 -0500375 error, Error::kNotConnected, "Not connected; request ignored.");
Darin Petkovfb0625e2012-01-16 13:05:56 +0100376 return;
377 }
Nathan Williamsb54974f2012-04-19 11:16:30 -0400378 // TODO(njw): See Connect() about possible weak ptr for 'this'.
379 ResultCallback cb = Bind(&Cellular::OnDisconnectReply, this);
380 capability_->Disconnect(error, cb);
381}
382
383// Note that there's no ResultCallback argument to this,
384// since Disconnect() isn't yet passed one.
385void Cellular::OnDisconnectReply(const Error &error) {
386 VLOG(2) << __func__ << "(" << error << ")";
387 if (error.IsSuccess())
388 OnDisconnected();
389 else
390 OnDisconnectFailed();
Darin Petkovfb0625e2012-01-16 13:05:56 +0100391}
392
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500393void Cellular::OnDisconnected() {
Darin Petkovfb0625e2012-01-16 13:05:56 +0100394 VLOG(2) << __func__;
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -0400395 if (state_ == kStateConnected || state_ == kStateLinked) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500396 SetState(kStateRegistered);
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -0400397 SetServiceFailureSilent(Service::kFailureUnknown);
398 } else {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500399 LOG(WARNING) << "Disconnect occurred while in state "
400 << GetStateString(state_);
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -0400401 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500402}
403
404void Cellular::OnDisconnectFailed() {
405 // TODO(ers): Signal failure.
Darin Petkovfb0625e2012-01-16 13:05:56 +0100406}
407
Darin Petkovbac96002011-08-09 13:22:00 -0700408void Cellular::EstablishLink() {
409 VLOG(2) << __func__;
Darin Petkov0828f5f2011-08-11 10:18:52 -0700410 CHECK_EQ(kStateConnected, state_);
411 unsigned int flags = 0;
Paul Stewartac4ac002011-08-26 12:04:26 -0700412 if (manager()->device_info()->GetFlags(interface_index(), &flags) &&
Darin Petkov0828f5f2011-08-11 10:18:52 -0700413 (flags & IFF_UP) != 0) {
414 LinkEvent(flags, IFF_UP);
415 return;
416 }
417 // TODO(petkov): Provide a timeout for a failed link-up request.
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700418 rtnl_handler()->SetInterfaceFlags(interface_index(), IFF_UP, IFF_UP);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700419}
420
421void Cellular::LinkEvent(unsigned int flags, unsigned int change) {
422 Device::LinkEvent(flags, change);
423 if ((flags & IFF_UP) != 0 && state_ == kStateConnected) {
Paul Stewartac4ac002011-08-26 12:04:26 -0700424 LOG(INFO) << link_name() << " is up.";
Darin Petkov0828f5f2011-08-11 10:18:52 -0700425 SetState(kStateLinked);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700426 // TODO(petkov): For GSM, remember the APN.
Paul Stewart2bf1d352011-12-06 15:02:55 -0800427 if (AcquireIPConfig()) {
Darin Petkov60b8c3b2011-08-25 11:03:20 -0700428 SelectService(service_);
429 SetServiceState(Service::kStateConfiguring);
430 } else {
431 LOG(ERROR) << "Unable to acquire DHCP config.";
432 }
Darin Petkov0828f5f2011-08-11 10:18:52 -0700433 } else if ((flags & IFF_UP) == 0 && state_ == kStateLinked) {
434 SetState(kStateConnected);
Darin Petkov2c377382012-01-11 11:40:43 +0100435 DestroyService();
Darin Petkov0828f5f2011-08-11 10:18:52 -0700436 }
Darin Petkovc5f56562011-08-06 16:40:05 -0700437}
438
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400439void Cellular::OnDBusPropertiesChanged(
440 const string &interface,
441 const DBusPropertiesMap &changed_properties,
442 const vector<string> &invalidated_properties) {
443 capability_->OnDBusPropertiesChanged(interface,
444 changed_properties,
445 invalidated_properties);
446}
447
Darin Petkovae0c64e2011-11-15 15:50:27 +0100448void Cellular::set_home_provider(const Operator &oper) {
449 home_provider_.CopyFrom(oper);
450}
451
Darin Petkovac635a82012-01-10 16:51:58 +0100452string Cellular::CreateFriendlyServiceName() {
453 VLOG(2) << __func__;
454 return capability_.get() ? capability_->CreateFriendlyServiceName() : "";
455}
456
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700457} // namespace shill