blob: b524e2eee371f148d59902191bf93ba2a70268e3 [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 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
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050021#include "shill/adaptor_interfaces.h"
Darin Petkovdaf43862011-10-27 11:37:28 +020022#include "shill/cellular_capability_cdma.h"
23#include "shill/cellular_capability_gsm.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;
Darin Petkovc0865312011-09-16 15:31:20 -070038using std::map;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070039using std::string;
Chris Masone889666b2011-07-03 12:58:50 -070040using std::vector;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070041
42namespace shill {
43
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,
Thieu Le3426c8f2012-01-11 17:35:11 -080086 Metrics *metrics,
Chris Masone3bd3c8c2011-06-13 08:20:26 -070087 Manager *manager,
Darin Petkove9d12e02011-07-27 15:09:37 -070088 const string &link_name,
Darin Petkov3335b372011-08-22 11:05:32 -070089 const string &address,
Darin Petkove9d12e02011-07-27 15:09:37 -070090 int interface_index,
91 Type type,
92 const string &owner,
Darin Petkov137884a2011-10-26 18:52:47 +020093 const string &path,
94 mobile_provider_db *provider_db)
Chris Masone3bd3c8c2011-06-13 08:20:26 -070095 : Device(control_interface,
96 dispatcher,
Thieu Le3426c8f2012-01-11 17:35:11 -080097 metrics,
Chris Masone3bd3c8c2011-06-13 08:20:26 -070098 manager,
Darin Petkove9d12e02011-07-27 15:09:37 -070099 link_name,
Chris Masone626719f2011-08-18 16:58:48 -0700100 address,
Gaurav Shah435de2c2011-11-17 19:01:07 -0800101 interface_index,
102 Technology::kCellular),
Darin Petkove9d12e02011-07-27 15:09:37 -0700103 state_(kStateDisabled),
Darin Petkovbac96002011-08-09 13:22:00 -0700104 modem_state_(kModemStateUnknown),
Darin Petkove9d12e02011-07-27 15:09:37 -0700105 dbus_owner_(owner),
106 dbus_path_(path),
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500107 provider_db_(provider_db) {
mukesh agrawalde29fa82011-09-16 16:16:36 -0700108 PropertyStore *store = this->mutable_store();
Paul Stewartac4ac002011-08-26 12:04:26 -0700109 store->RegisterConstString(flimflam::kDBusConnectionProperty, &dbus_owner_);
110 store->RegisterConstString(flimflam::kDBusObjectProperty, &dbus_path_);
Paul Stewartac4ac002011-08-26 12:04:26 -0700111 store->RegisterConstStringmap(flimflam::kHomeProviderProperty,
Darin Petkov3335b372011-08-22 11:05:32 -0700112 &home_provider_.ToDict());
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500113 // For now, only a single capability is supported.
114 InitCapability(type, ProxyFactory::GetInstance());
Chris Masoneb925cc82011-06-22 15:39:57 -0700115
Darin Petkov5f316f62011-11-18 12:10:26 +0100116 VLOG(2) << "Cellular device " << this->link_name() << " initialized.";
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700117}
118
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500119Cellular::~Cellular() {
120}
Darin Petkove9d12e02011-07-27 15:09:37 -0700121
Darin Petkovcc044422011-08-17 13:30:06 -0700122// static
123string Cellular::GetStateString(State state) {
124 switch (state) {
Darin Petkove9d12e02011-07-27 15:09:37 -0700125 case kStateDisabled: return "CellularStateDisabled";
126 case kStateEnabled: return "CellularStateEnabled";
127 case kStateRegistered: return "CellularStateRegistered";
128 case kStateConnected: return "CellularStateConnected";
Darin Petkov0828f5f2011-08-11 10:18:52 -0700129 case kStateLinked: return "CellularStateLinked";
130 default: NOTREACHED();
Darin Petkove9d12e02011-07-27 15:09:37 -0700131 }
Darin Petkovcc044422011-08-17 13:30:06 -0700132 return StringPrintf("CellularStateUnknown-%d", state);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700133}
134
135void Cellular::SetState(State state) {
Darin Petkovcc044422011-08-17 13:30:06 -0700136 VLOG(2) << GetStateString(state_) << " -> " << GetStateString(state);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700137 state_ = state;
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700138}
139
140void Cellular::Start() {
Darin Petkovcc044422011-08-17 13:30:06 -0700141 LOG(INFO) << __func__ << ": " << GetStateString(state_);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500142 if (state_ != kStateDisabled) {
143 return;
144 }
Darin Petkov3335b372011-08-22 11:05:32 -0700145 Device::Start();
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500146 if (modem_state_ == kModemStateEnabled) {
147 // Modem already enabled.
148 OnModemEnabled();
149 return;
150 }
151 // TODO(ers): this should not be done automatically. It should
152 // require an explicit Enable request to start the modem.
153 capability_->StartModem();
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700154}
155
156void Cellular::Stop() {
Darin Petkovfb0625e2012-01-16 13:05:56 +0100157 DestroyService();
158 DisconnectModem();
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500159 if (state_ != kStateDisabled)
160 capability_->DisableModem(NULL);
161 capability_->StopModem();
Darin Petkov3335b372011-08-22 11:05:32 -0700162 Device::Stop();
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700163}
164
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500165void Cellular::InitCapability(Type type, ProxyFactory *proxy_factory) {
Darin Petkov5f316f62011-11-18 12:10:26 +0100166 // TODO(petkov): Consider moving capability construction into a factory that's
167 // external to the Cellular class.
168 VLOG(2) << __func__ << "(" << type << ")";
169 switch (type) {
Darin Petkovdaf43862011-10-27 11:37:28 +0200170 case kTypeGSM:
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500171 capability_.reset(new CellularCapabilityGSM(this, proxy_factory));
Darin Petkovdaf43862011-10-27 11:37:28 +0200172 break;
173 case kTypeCDMA:
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500174 capability_.reset(new CellularCapabilityCDMA(this, proxy_factory));
Darin Petkovdaf43862011-10-27 11:37:28 +0200175 break;
176 default: NOTREACHED();
177 }
178}
179
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500180void Cellular::OnModemEnabled() {
181 VLOG(2) << __func__ << ": " << GetStateString(state_);
Darin Petkovfb0625e2012-01-16 13:05:56 +0100182 if (state_ == kStateDisabled) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500183 SetState(kStateEnabled);
Darin Petkovfb0625e2012-01-16 13:05:56 +0100184 }
Darin Petkovfb0625e2012-01-16 13:05:56 +0100185}
186
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500187void Cellular::OnModemDisabled() {
188 VLOG(2) << __func__ << ": " << GetStateString(state_);
189 if (state_ != kStateDisabled) {
190 SetState(kStateDisabled);
Darin Petkovd2045802011-08-23 11:09:25 -0700191 }
Darin Petkovceb68172011-07-29 14:47:48 -0700192}
193
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500194void Cellular::Activate(const std::string &carrier,
195 ReturnerInterface *returner) {
196 capability_->Activate(carrier, new AsyncCallHandler(returner));
Darin Petkov9ae310f2011-08-30 15:41:13 -0700197}
198
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500199void Cellular::RegisterOnNetwork(const string &network_id,
200 ReturnerInterface *returner) {
201 capability_->RegisterOnNetwork(network_id, new AsyncCallHandler(returner));
Darin Petkova3d3be52011-11-14 21:34:16 +0100202}
203
Darin Petkovc64fe5e2012-01-11 12:46:13 +0100204void Cellular::RequirePIN(
205 const string &pin, bool require, ReturnerInterface *returner) {
206 VLOG(2) << __func__ << "(" << returner << ")";
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500207 capability_->RequirePIN(pin, require, new AsyncCallHandler(returner));
Darin Petkove42e1012011-08-31 12:35:04 -0700208}
209
Darin Petkove5bc2cb2011-12-07 14:47:32 +0100210void Cellular::EnterPIN(const string &pin, ReturnerInterface *returner) {
211 VLOG(2) << __func__ << "(" << returner << ")";
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500212 capability_->EnterPIN(pin, new AsyncCallHandler(returner));
Darin Petkove42e1012011-08-31 12:35:04 -0700213}
214
Darin Petkovc64fe5e2012-01-11 12:46:13 +0100215void Cellular::UnblockPIN(const string &unblock_code,
216 const string &pin,
217 ReturnerInterface *returner) {
218 VLOG(2) << __func__ << "(" << returner << ")";
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500219 capability_->UnblockPIN(unblock_code, pin, new AsyncCallHandler(returner));
Darin Petkove42e1012011-08-31 12:35:04 -0700220}
221
Darin Petkovb05315f2011-11-07 10:14:25 +0100222void Cellular::ChangePIN(
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500223 const string &old_pin, const string &new_pin,
224 ReturnerInterface *returner) {
Darin Petkovc64fe5e2012-01-11 12:46:13 +0100225 VLOG(2) << __func__ << "(" << returner << ")";
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500226 capability_->ChangePIN(old_pin, new_pin, new AsyncCallHandler(returner));
Darin Petkove42e1012011-08-31 12:35:04 -0700227}
228
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500229void Cellular::Scan(Error * /*error*/) {
230 // TODO(ers): for now report immediate success.
231 capability_->Scan(NULL);
Darin Petkovceb68172011-07-29 14:47:48 -0700232}
233
Darin Petkovd9661952011-08-03 16:25:42 -0700234void Cellular::HandleNewRegistrationState() {
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500235 dispatcher()->PostTask(Bind(&Cellular::HandleNewRegistrationStateTask, this));
Darin Petkov0828f5f2011-08-11 10:18:52 -0700236}
237
238void Cellular::HandleNewRegistrationStateTask() {
Darin Petkovd9661952011-08-03 16:25:42 -0700239 VLOG(2) << __func__;
Darin Petkovb72cf402011-11-22 14:51:39 +0100240 if (!capability_->IsRegistered()) {
Darin Petkov2c377382012-01-11 11:40:43 +0100241 DestroyService();
Darin Petkov0828f5f2011-08-11 10:18:52 -0700242 if (state_ == kStateLinked ||
243 state_ == kStateConnected ||
244 state_ == kStateRegistered) {
245 SetState(kStateEnabled);
Darin Petkovd9661952011-08-03 16:25:42 -0700246 }
247 return;
248 }
Darin Petkovd9661952011-08-03 16:25:42 -0700249 if (state_ == kStateEnabled) {
Darin Petkov0828f5f2011-08-11 10:18:52 -0700250 SetState(kStateRegistered);
Darin Petkovd9661952011-08-03 16:25:42 -0700251 }
252 if (!service_.get()) {
Darin Petkovd9661952011-08-03 16:25:42 -0700253 CreateService();
254 }
Darin Petkov3e509242011-11-10 14:46:44 +0100255 capability_->GetSignalQuality();
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500256 if (state_ == kStateRegistered && modem_state_ == kModemStateConnected)
257 OnConnected();
Darin Petkovb72cf402011-11-22 14:51:39 +0100258 service_->SetNetworkTechnology(capability_->GetNetworkTechnologyString());
259 service_->SetRoamingState(capability_->GetRoamingStateString());
Darin Petkovd9661952011-08-03 16:25:42 -0700260}
261
Darin Petkovd9661952011-08-03 16:25:42 -0700262void Cellular::HandleNewSignalQuality(uint32 strength) {
263 VLOG(2) << "Signal strength: " << strength;
Darin Petkovd78ee7e2012-01-12 11:21:10 +0100264 if (service_) {
265 service_->SetStrength(strength);
Darin Petkovd9661952011-08-03 16:25:42 -0700266 }
267}
268
269void Cellular::CreateService() {
Darin Petkov0828f5f2011-08-11 10:18:52 -0700270 VLOG(2) << __func__;
Darin Petkovd9661952011-08-03 16:25:42 -0700271 CHECK(!service_.get());
272 service_ =
Thieu Le3426c8f2012-01-11 17:35:11 -0800273 new CellularService(control_interface(), dispatcher(), metrics(),
274 manager(), this);
Darin Petkovae0c64e2011-11-15 15:50:27 +0100275 capability_->OnServiceCreated();
Darin Petkov31332412012-01-28 01:50:02 +0100276 manager()->RegisterService(service_);
Darin Petkovf5f61e02011-07-29 11:35:40 -0700277}
278
Darin Petkov2c377382012-01-11 11:40:43 +0100279void Cellular::DestroyService() {
280 VLOG(2) << __func__;
281 DestroyIPConfig();
282 if (service_) {
283 manager()->DeregisterService(service_);
284 service_ = NULL;
285 }
286 SelectService(NULL);
287}
288
Paul Stewartfdd16072011-09-16 12:41:35 -0700289bool Cellular::TechnologyIs(const Technology::Identifier type) const {
290 return type == Technology::kCellular;
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700291}
292
Darin Petkov4d6d9412011-08-24 13:19:54 -0700293void Cellular::Connect(Error *error) {
Darin Petkovc5f56562011-08-06 16:40:05 -0700294 VLOG(2) << __func__;
Darin Petkov0828f5f2011-08-11 10:18:52 -0700295 if (state_ == kStateConnected ||
296 state_ == kStateLinked) {
Paul Stewartbe005172011-11-02 18:10:29 -0700297 Error::PopulateAndLog(error, Error::kAlreadyConnected,
298 "Already connected; connection request ignored.");
Darin Petkovc5f56562011-08-06 16:40:05 -0700299 return;
300 }
301 CHECK_EQ(kStateRegistered, state_);
Darin Petkovd2045802011-08-23 11:09:25 -0700302
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500303 if (!capability_->allow_roaming() &&
Darin Petkovd2045802011-08-23 11:09:25 -0700304 service_->roaming_state() == flimflam::kRoamingStateRoaming) {
Paul Stewartbe005172011-11-02 18:10:29 -0700305 Error::PopulateAndLog(error, Error::kNotOnHomeNetwork,
306 "Roaming disallowed; connection request ignored.");
Darin Petkovd2045802011-08-23 11:09:25 -0700307 return;
308 }
309
Darin Petkovc5f56562011-08-06 16:40:05 -0700310 DBusPropertiesMap properties;
Darin Petkovae0c64e2011-11-15 15:50:27 +0100311 capability_->SetupConnectProperties(&properties);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500312 capability_->Connect(properties);
Darin Petkovc5f56562011-08-06 16:40:05 -0700313}
314
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500315void Cellular::OnConnected() {
Darin Petkovc5f56562011-08-06 16:40:05 -0700316 VLOG(2) << __func__;
Darin Petkov0828f5f2011-08-11 10:18:52 -0700317 SetState(kStateConnected);
Darin Petkov9c1dcef2012-02-07 15:58:26 +0100318 if (!capability_->allow_roaming() &&
319 service_->roaming_state() == flimflam::kRoamingStateRoaming) {
320 Disconnect(NULL);
321 } else {
322 EstablishLink();
323 }
Darin Petkovbac96002011-08-09 13:22:00 -0700324}
325
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500326void Cellular::OnConnectFailed() {
327 // TODO(ers): Signal failure.
328}
329
Darin Petkovfb0625e2012-01-16 13:05:56 +0100330void Cellular::Disconnect(Error *error) {
331 VLOG(2) << __func__;
332 if (state_ != kStateConnected &&
333 state_ != kStateLinked) {
334 Error::PopulateAndLog(
335 error, Error::kInProgress, "Not connected; request ignored.");
336 return;
337 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500338 capability_->Disconnect();
Darin Petkovfb0625e2012-01-16 13:05:56 +0100339}
340
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500341void Cellular::OnDisconnected() {
Darin Petkovfb0625e2012-01-16 13:05:56 +0100342 VLOG(2) << __func__;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500343 SetState(kStateRegistered);
Darin Petkovfb0625e2012-01-16 13:05:56 +0100344}
345
346void Cellular::DisconnectModem() {
347 VLOG(2) << __func__;
348 if (state_ != kStateConnected &&
349 state_ != kStateLinked) {
350 return;
351 }
352 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583). Note,
353 // however, that this is invoked by the Stop method, so some extra refactoring
354 // may be needed to prevent the device instance from being destroyed before
355 // the modem manager calls are complete. Maybe Disconnect and Disable need to
356 // be handled by the parent Modem class.
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500357 capability_->Disconnect();
358}
359
360void Cellular::OnDisconnectFailed() {
361 // TODO(ers): Signal failure.
Darin Petkovfb0625e2012-01-16 13:05:56 +0100362}
363
Darin Petkovbac96002011-08-09 13:22:00 -0700364void Cellular::EstablishLink() {
365 VLOG(2) << __func__;
Darin Petkov0828f5f2011-08-11 10:18:52 -0700366 CHECK_EQ(kStateConnected, state_);
367 unsigned int flags = 0;
Paul Stewartac4ac002011-08-26 12:04:26 -0700368 if (manager()->device_info()->GetFlags(interface_index(), &flags) &&
Darin Petkov0828f5f2011-08-11 10:18:52 -0700369 (flags & IFF_UP) != 0) {
370 LinkEvent(flags, IFF_UP);
371 return;
372 }
373 // TODO(petkov): Provide a timeout for a failed link-up request.
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700374 rtnl_handler()->SetInterfaceFlags(interface_index(), IFF_UP, IFF_UP);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700375}
376
377void Cellular::LinkEvent(unsigned int flags, unsigned int change) {
378 Device::LinkEvent(flags, change);
379 if ((flags & IFF_UP) != 0 && state_ == kStateConnected) {
Paul Stewartac4ac002011-08-26 12:04:26 -0700380 LOG(INFO) << link_name() << " is up.";
Darin Petkov0828f5f2011-08-11 10:18:52 -0700381 SetState(kStateLinked);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700382 // TODO(petkov): For GSM, remember the APN.
Paul Stewart2bf1d352011-12-06 15:02:55 -0800383 if (AcquireIPConfig()) {
Darin Petkov60b8c3b2011-08-25 11:03:20 -0700384 SelectService(service_);
385 SetServiceState(Service::kStateConfiguring);
386 } else {
387 LOG(ERROR) << "Unable to acquire DHCP config.";
388 }
Darin Petkov0828f5f2011-08-11 10:18:52 -0700389 } else if ((flags & IFF_UP) == 0 && state_ == kStateLinked) {
390 SetState(kStateConnected);
Darin Petkov2c377382012-01-11 11:40:43 +0100391 DestroyService();
Darin Petkov0828f5f2011-08-11 10:18:52 -0700392 }
Darin Petkovc5f56562011-08-06 16:40:05 -0700393}
394
Darin Petkovae0c64e2011-11-15 15:50:27 +0100395void Cellular::OnModemManagerPropertiesChanged(
396 const DBusPropertiesMap &properties) {
Darin Petkov721ac932011-11-16 15:43:09 +0100397 capability_->OnModemManagerPropertiesChanged(properties);
Chris Masone889666b2011-07-03 12:58:50 -0700398}
399
Darin Petkovae0c64e2011-11-15 15:50:27 +0100400void Cellular::set_home_provider(const Operator &oper) {
401 home_provider_.CopyFrom(oper);
402}
403
Darin Petkovac635a82012-01-10 16:51:58 +0100404string Cellular::CreateFriendlyServiceName() {
405 VLOG(2) << __func__;
406 return capability_.get() ? capability_->CreateFriendlyServiceName() : "";
407}
408
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700409} // namespace shill