blob: 9c8ff5694e7d2522296a8a8cca129b236708faa0 [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
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"
Gaurav Shah435de2c2011-11-17 19:01:07 -080034#include "shill/technology.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070035
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 Petkov0a4dfeb2011-11-18 19:36:13 +010043const char Cellular::kPropertyIMSI[] = "imsi";
Darin Petkovc5f56562011-08-06 16:40:05 -070044
Darin Petkov3335b372011-08-22 11:05:32 -070045Cellular::Operator::Operator() {
46 SetName("");
47 SetCode("");
48 SetCountry("");
49}
50
51Cellular::Operator::~Operator() {}
52
53void Cellular::Operator::CopyFrom(const Operator &oper) {
54 dict_ = oper.dict_;
55}
56
57const string &Cellular::Operator::GetName() const {
58 return dict_.find(flimflam::kOperatorNameKey)->second;
59}
60
61void Cellular::Operator::SetName(const string &name) {
62 dict_[flimflam::kOperatorNameKey] = name;
63}
64
65const string &Cellular::Operator::GetCode() const {
66 return dict_.find(flimflam::kOperatorCodeKey)->second;
67}
68
69void Cellular::Operator::SetCode(const string &code) {
70 dict_[flimflam::kOperatorCodeKey] = code;
71}
72
73const string &Cellular::Operator::GetCountry() const {
74 return dict_.find(flimflam::kOperatorCountryKey)->second;
75}
76
77void Cellular::Operator::SetCountry(const string &country) {
78 dict_[flimflam::kOperatorCountryKey] = country;
79}
80
81const Stringmap &Cellular::Operator::ToDict() const {
82 return dict_;
83}
84
Chris Masone3bd3c8c2011-06-13 08:20:26 -070085Cellular::Cellular(ControlInterface *control_interface,
86 EventDispatcher *dispatcher,
Thieu Le3426c8f2012-01-11 17:35:11 -080087 Metrics *metrics,
Chris Masone3bd3c8c2011-06-13 08:20:26 -070088 Manager *manager,
Darin Petkove9d12e02011-07-27 15:09:37 -070089 const string &link_name,
Darin Petkov3335b372011-08-22 11:05:32 -070090 const string &address,
Darin Petkove9d12e02011-07-27 15:09:37 -070091 int interface_index,
92 Type type,
93 const string &owner,
Darin Petkov137884a2011-10-26 18:52:47 +020094 const string &path,
95 mobile_provider_db *provider_db)
Chris Masone3bd3c8c2011-06-13 08:20:26 -070096 : Device(control_interface,
97 dispatcher,
Thieu Le3426c8f2012-01-11 17:35:11 -080098 metrics,
Chris Masone3bd3c8c2011-06-13 08:20:26 -070099 manager,
Darin Petkove9d12e02011-07-27 15:09:37 -0700100 link_name,
Chris Masone626719f2011-08-18 16:58:48 -0700101 address,
Gaurav Shah435de2c2011-11-17 19:01:07 -0800102 interface_index,
103 Technology::kCellular),
Darin Petkovab565bb2011-10-06 02:55:51 -0700104 proxy_factory_(ProxyFactory::GetInstance()),
Darin Petkove9d12e02011-07-27 15:09:37 -0700105 state_(kStateDisabled),
Darin Petkovbac96002011-08-09 13:22:00 -0700106 modem_state_(kModemStateUnknown),
Darin Petkove9d12e02011-07-27 15:09:37 -0700107 dbus_owner_(owner),
108 dbus_path_(path),
Darin Petkov137884a2011-10-26 18:52:47 +0200109 provider_db_(provider_db),
Darin Petkovc5f56562011-08-06 16:40:05 -0700110 task_factory_(this),
Darin Petkov1272a432011-11-10 15:53:37 +0100111 allow_roaming_(false) {
mukesh agrawalde29fa82011-09-16 16:16:36 -0700112 PropertyStore *store = this->mutable_store();
Paul Stewartac4ac002011-08-26 12:04:26 -0700113 store->RegisterConstString(flimflam::kCarrierProperty, &carrier_);
114 store->RegisterConstString(flimflam::kDBusConnectionProperty, &dbus_owner_);
115 store->RegisterConstString(flimflam::kDBusObjectProperty, &dbus_path_);
116 store->RegisterBool(flimflam::kCellularAllowRoamingProperty, &allow_roaming_);
117 store->RegisterConstString(flimflam::kEsnProperty, &esn_);
118 store->RegisterConstString(flimflam::kFirmwareRevisionProperty,
Chris Masone27c4aa52011-07-02 13:10:14 -0700119 &firmware_revision_);
Paul Stewartac4ac002011-08-26 12:04:26 -0700120 store->RegisterConstString(flimflam::kHardwareRevisionProperty,
Chris Masone27c4aa52011-07-02 13:10:14 -0700121 &hardware_revision_);
Paul Stewartac4ac002011-08-26 12:04:26 -0700122 store->RegisterConstStringmap(flimflam::kHomeProviderProperty,
Darin Petkov3335b372011-08-22 11:05:32 -0700123 &home_provider_.ToDict());
Paul Stewartac4ac002011-08-26 12:04:26 -0700124 store->RegisterConstString(flimflam::kImeiProperty, &imei_);
125 store->RegisterConstString(flimflam::kImsiProperty, &imsi_);
126 store->RegisterConstString(flimflam::kManufacturerProperty, &manufacturer_);
127 store->RegisterConstString(flimflam::kMdnProperty, &mdn_);
128 store->RegisterConstString(flimflam::kMeidProperty, &meid_);
129 store->RegisterConstString(flimflam::kMinProperty, &min_);
130 store->RegisterConstString(flimflam::kModelIDProperty, &model_id_);
Chris Masoneb925cc82011-06-22 15:39:57 -0700131
Darin Petkov5f316f62011-11-18 12:10:26 +0100132 InitCapability(type); // For now, only a single capability is supported.
Chris Masoneb925cc82011-06-22 15:39:57 -0700133
Darin Petkov5f316f62011-11-18 12:10:26 +0100134 VLOG(2) << "Cellular device " << this->link_name() << " initialized.";
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 -0700139// static
140string Cellular::GetStateString(State state) {
141 switch (state) {
Darin Petkove9d12e02011-07-27 15:09:37 -0700142 case kStateDisabled: return "CellularStateDisabled";
143 case kStateEnabled: return "CellularStateEnabled";
144 case kStateRegistered: return "CellularStateRegistered";
145 case kStateConnected: return "CellularStateConnected";
Darin Petkov0828f5f2011-08-11 10:18:52 -0700146 case kStateLinked: return "CellularStateLinked";
147 default: NOTREACHED();
Darin Petkove9d12e02011-07-27 15:09:37 -0700148 }
Darin Petkovcc044422011-08-17 13:30:06 -0700149 return StringPrintf("CellularStateUnknown-%d", state);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700150}
151
152void Cellular::SetState(State state) {
Darin Petkovcc044422011-08-17 13:30:06 -0700153 VLOG(2) << GetStateString(state_) << " -> " << GetStateString(state);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700154 state_ = state;
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700155}
156
157void Cellular::Start() {
Darin Petkovcc044422011-08-17 13:30:06 -0700158 LOG(INFO) << __func__ << ": " << GetStateString(state_);
Darin Petkov3335b372011-08-22 11:05:32 -0700159 Device::Start();
Darin Petkov5f316f62011-11-18 12:10:26 +0100160 capability_->OnDeviceStarted();
Darin Petkovbec79a22011-08-01 14:47:17 -0700161 InitProxies();
Darin Petkovf5f61e02011-07-29 11:35:40 -0700162 EnableModem();
Darin Petkov184c54e2011-11-15 12:44:39 +0100163 capability_->Register();
Darin Petkovf5f61e02011-07-29 11:35:40 -0700164 GetModemStatus();
Darin Petkovcb547732011-11-09 13:55:26 +0100165 capability_->GetIdentifiers();
Darin Petkov184c54e2011-11-15 12:44:39 +0100166 capability_->GetProperties();
Darin Petkovceb68172011-07-29 14:47:48 -0700167 GetModemInfo();
Darin Petkov184c54e2011-11-15 12:44:39 +0100168 capability_->GetRegistrationState();
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700169}
170
171void Cellular::Stop() {
Darin Petkov5f316f62011-11-18 12:10:26 +0100172 capability_->OnDeviceStopped();
Darin Petkovfb0625e2012-01-16 13:05:56 +0100173 DestroyService();
174 DisconnectModem();
175 DisableModem();
Darin Petkove9d12e02011-07-27 15:09:37 -0700176 proxy_.reset();
Darin Petkove604f702011-07-28 15:51:17 -0700177 simple_proxy_.reset();
Darin Petkov3335b372011-08-22 11:05:32 -0700178 Device::Stop();
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700179}
180
Darin Petkov5f316f62011-11-18 12:10:26 +0100181void Cellular::InitCapability(Type type) {
182 // TODO(petkov): Consider moving capability construction into a factory that's
183 // external to the Cellular class.
184 VLOG(2) << __func__ << "(" << type << ")";
185 switch (type) {
Darin Petkovdaf43862011-10-27 11:37:28 +0200186 case kTypeGSM:
187 capability_.reset(new CellularCapabilityGSM(this));
188 break;
189 case kTypeCDMA:
190 capability_.reset(new CellularCapabilityCDMA(this));
191 break;
192 default: NOTREACHED();
193 }
194}
195
Darin Petkovbec79a22011-08-01 14:47:17 -0700196void Cellular::InitProxies() {
Darin Petkovcc044422011-08-17 13:30:06 -0700197 VLOG(2) << __func__;
Darin Petkovab565bb2011-10-06 02:55:51 -0700198 proxy_.reset(proxy_factory_->CreateModemProxy(this, dbus_path_, dbus_owner_));
Darin Petkovbec79a22011-08-01 14:47:17 -0700199 simple_proxy_.reset(
Darin Petkovab565bb2011-10-06 02:55:51 -0700200 proxy_factory_->CreateModemSimpleProxy(dbus_path_, dbus_owner_));
Darin Petkovbec79a22011-08-01 14:47:17 -0700201}
202
Darin Petkovf5f61e02011-07-29 11:35:40 -0700203void Cellular::EnableModem() {
204 CHECK_EQ(kStateDisabled, state_);
205 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Darin Petkove5bc2cb2011-12-07 14:47:32 +0100206 try {
207 proxy_->Enable(true);
208 } catch (const DBus::Error e) {
209 LOG(WARNING) << "Enable failed: " << e.what();
210 }
Darin Petkov0828f5f2011-08-11 10:18:52 -0700211 SetState(kStateEnabled);
Darin Petkovf5f61e02011-07-29 11:35:40 -0700212}
213
Darin Petkovfb0625e2012-01-16 13:05:56 +0100214void Cellular::DisableModem() {
215 VLOG(2) << __func__;
216 if (state_ == kStateDisabled) {
217 return;
218 }
219 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583). Note,
220 // however, that this is invoked by the Stop method, so some extra refactoring
221 // may be needed to prevent the device instance from being destroyed before
222 // the modem manager calls are complete. Maybe Disconnect and Disable need to
223 // be handled by the parent Modem class.
224 try {
225 proxy_->Enable(false);
226 } catch (const DBus::Error e) {
227 LOG(WARNING) << "Disable failed: " << e.what();
228 }
229 SetState(kStateDisabled);
230}
231
Darin Petkovf5f61e02011-07-29 11:35:40 -0700232void Cellular::GetModemStatus() {
Darin Petkovceb68172011-07-29 14:47:48 -0700233 CHECK_EQ(kStateEnabled, state_);
Darin Petkovf5f61e02011-07-29 11:35:40 -0700234 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
235 DBusPropertiesMap properties = simple_proxy_->GetStatus();
Darin Petkovae0c64e2011-11-15 15:50:27 +0100236 DBusProperties::GetString(properties, "carrier", &carrier_);
Darin Petkovceb68172011-07-29 14:47:48 -0700237 DBusProperties::GetString(properties, "meid", &meid_);
238 DBusProperties::GetString(properties, "imei", &imei_);
Darin Petkov0a4dfeb2011-11-18 19:36:13 +0100239 DBusProperties::GetString(properties, kPropertyIMSI, &imsi_);
Darin Petkovceb68172011-07-29 14:47:48 -0700240 DBusProperties::GetString(properties, "esn", &esn_);
241 DBusProperties::GetString(properties, "mdn", &mdn_);
242 DBusProperties::GetString(properties, "min", &min_);
Darin Petkovceb68172011-07-29 14:47:48 -0700243 DBusProperties::GetString(
244 properties, "firmware_revision", &firmware_revision_);
Darin Petkovb27e5442011-08-16 14:36:45 -0700245
Darin Petkovd2045802011-08-23 11:09:25 -0700246 uint32 state = 0;
247 if (DBusProperties::GetUint32(properties, "state", &state)) {
248 modem_state_ = static_cast<ModemState>(state);
249 }
Darin Petkovb27e5442011-08-16 14:36:45 -0700250
Darin Petkovae0c64e2011-11-15 15:50:27 +0100251 capability_->UpdateStatus(properties);
Darin Petkovceb68172011-07-29 14:47:48 -0700252}
253
Darin Petkov184c54e2011-11-15 12:44:39 +0100254void Cellular::Activate(const std::string &carrier, Error *error) {
255 capability_->Activate(carrier, error);
Darin Petkov9ae310f2011-08-30 15:41:13 -0700256}
257
258void Cellular::RegisterOnNetwork(const string &network_id, Error *error) {
Darin Petkov184c54e2011-11-15 12:44:39 +0100259 capability_->RegisterOnNetwork(network_id, error);
Darin Petkova3d3be52011-11-14 21:34:16 +0100260}
261
Darin Petkovc64fe5e2012-01-11 12:46:13 +0100262void Cellular::RequirePIN(
263 const string &pin, bool require, ReturnerInterface *returner) {
264 VLOG(2) << __func__ << "(" << returner << ")";
265 capability_->RequirePIN(pin, require, returner);
Darin Petkove42e1012011-08-31 12:35:04 -0700266}
267
Darin Petkove5bc2cb2011-12-07 14:47:32 +0100268void Cellular::EnterPIN(const string &pin, ReturnerInterface *returner) {
269 VLOG(2) << __func__ << "(" << returner << ")";
270 capability_->EnterPIN(pin, returner);
Darin Petkove42e1012011-08-31 12:35:04 -0700271}
272
Darin Petkovc64fe5e2012-01-11 12:46:13 +0100273void Cellular::UnblockPIN(const string &unblock_code,
274 const string &pin,
275 ReturnerInterface *returner) {
276 VLOG(2) << __func__ << "(" << returner << ")";
277 capability_->UnblockPIN(unblock_code, pin, returner);
Darin Petkove42e1012011-08-31 12:35:04 -0700278}
279
Darin Petkovb05315f2011-11-07 10:14:25 +0100280void Cellular::ChangePIN(
Darin Petkovc64fe5e2012-01-11 12:46:13 +0100281 const string &old_pin, const string &new_pin, ReturnerInterface *returner) {
282 VLOG(2) << __func__ << "(" << returner << ")";
283 capability_->ChangePIN(old_pin, new_pin, returner);
Darin Petkove42e1012011-08-31 12:35:04 -0700284}
285
Darin Petkov1272a432011-11-10 15:53:37 +0100286void Cellular::Scan(Error *error) {
287 capability_->Scan(error);
288}
289
Darin Petkovceb68172011-07-29 14:47:48 -0700290void Cellular::GetModemInfo() {
Darin Petkovd2045802011-08-23 11:09:25 -0700291 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Darin Petkovceb68172011-07-29 14:47:48 -0700292 ModemProxyInterface::Info info = proxy_->GetInfo();
293 manufacturer_ = info._1;
294 model_id_ = info._2;
295 hardware_revision_ = info._3;
296 VLOG(2) << "ModemInfo: " << manufacturer_ << ", " << model_id_ << ", "
297 << hardware_revision_;
298}
299
Darin Petkovd9661952011-08-03 16:25:42 -0700300void Cellular::HandleNewRegistrationState() {
Paul Stewartac4ac002011-08-26 12:04:26 -0700301 dispatcher()->PostTask(
Darin Petkov0828f5f2011-08-11 10:18:52 -0700302 task_factory_.NewRunnableMethod(
303 &Cellular::HandleNewRegistrationStateTask));
304}
305
306void Cellular::HandleNewRegistrationStateTask() {
Darin Petkovd9661952011-08-03 16:25:42 -0700307 VLOG(2) << __func__;
Darin Petkovb72cf402011-11-22 14:51:39 +0100308 if (!capability_->IsRegistered()) {
Darin Petkov2c377382012-01-11 11:40:43 +0100309 DestroyService();
Darin Petkov0828f5f2011-08-11 10:18:52 -0700310 if (state_ == kStateLinked ||
311 state_ == kStateConnected ||
312 state_ == kStateRegistered) {
313 SetState(kStateEnabled);
Darin Petkovd9661952011-08-03 16:25:42 -0700314 }
315 return;
316 }
Darin Petkovd9661952011-08-03 16:25:42 -0700317 if (state_ == kStateEnabled) {
Darin Petkov0828f5f2011-08-11 10:18:52 -0700318 SetState(kStateRegistered);
Darin Petkovd9661952011-08-03 16:25:42 -0700319 }
320 if (!service_.get()) {
321 // For now, no endpoint is created. Revisit if necessary.
322 CreateService();
323 }
Darin Petkov3e509242011-11-10 14:46:44 +0100324 capability_->GetSignalQuality();
Darin Petkov0828f5f2011-08-11 10:18:52 -0700325 if (state_ == kStateRegistered && modem_state_ == kModemStateConnected) {
326 SetState(kStateConnected);
327 EstablishLink();
328 }
Darin Petkovb72cf402011-11-22 14:51:39 +0100329 service_->SetNetworkTechnology(capability_->GetNetworkTechnologyString());
330 service_->SetRoamingState(capability_->GetRoamingStateString());
Darin Petkovd9661952011-08-03 16:25:42 -0700331}
332
Darin Petkovd9661952011-08-03 16:25:42 -0700333void Cellular::HandleNewSignalQuality(uint32 strength) {
334 VLOG(2) << "Signal strength: " << strength;
Darin Petkovd78ee7e2012-01-12 11:21:10 +0100335 if (service_) {
336 service_->SetStrength(strength);
Darin Petkovd9661952011-08-03 16:25:42 -0700337 }
338}
339
340void Cellular::CreateService() {
Darin Petkov0828f5f2011-08-11 10:18:52 -0700341 VLOG(2) << __func__;
Darin Petkovd9661952011-08-03 16:25:42 -0700342 CHECK(!service_.get());
343 service_ =
Thieu Le3426c8f2012-01-11 17:35:11 -0800344 new CellularService(control_interface(), dispatcher(), metrics(),
345 manager(), this);
Darin Petkovae0c64e2011-11-15 15:50:27 +0100346 capability_->OnServiceCreated();
Darin Petkovf5f61e02011-07-29 11:35:40 -0700347}
348
Darin Petkov2c377382012-01-11 11:40:43 +0100349void Cellular::DestroyService() {
350 VLOG(2) << __func__;
351 DestroyIPConfig();
352 if (service_) {
353 manager()->DeregisterService(service_);
354 service_ = NULL;
355 }
356 SelectService(NULL);
357}
358
Paul Stewartfdd16072011-09-16 12:41:35 -0700359bool Cellular::TechnologyIs(const Technology::Identifier type) const {
360 return type == Technology::kCellular;
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700361}
362
Darin Petkov4d6d9412011-08-24 13:19:54 -0700363void Cellular::Connect(Error *error) {
Darin Petkovc5f56562011-08-06 16:40:05 -0700364 VLOG(2) << __func__;
Darin Petkov0828f5f2011-08-11 10:18:52 -0700365 if (state_ == kStateConnected ||
366 state_ == kStateLinked) {
Paul Stewartbe005172011-11-02 18:10:29 -0700367 Error::PopulateAndLog(error, Error::kAlreadyConnected,
368 "Already connected; connection request ignored.");
Darin Petkovc5f56562011-08-06 16:40:05 -0700369 return;
370 }
371 CHECK_EQ(kStateRegistered, state_);
Darin Petkovd2045802011-08-23 11:09:25 -0700372
373 if (!allow_roaming_ &&
374 service_->roaming_state() == flimflam::kRoamingStateRoaming) {
Paul Stewartbe005172011-11-02 18:10:29 -0700375 Error::PopulateAndLog(error, Error::kNotOnHomeNetwork,
376 "Roaming disallowed; connection request ignored.");
Darin Petkovd2045802011-08-23 11:09:25 -0700377 return;
378 }
379
Darin Petkovc5f56562011-08-06 16:40:05 -0700380 DBusPropertiesMap properties;
Darin Petkovae0c64e2011-11-15 15:50:27 +0100381 capability_->SetupConnectProperties(&properties);
Darin Petkovc5f56562011-08-06 16:40:05 -0700382
383 // Defer connect because we may be in a dbus-c++ callback.
Paul Stewartac4ac002011-08-26 12:04:26 -0700384 dispatcher()->PostTask(
Darin Petkovc5f56562011-08-06 16:40:05 -0700385 task_factory_.NewRunnableMethod(&Cellular::ConnectTask, properties));
386}
387
388void Cellular::ConnectTask(const DBusPropertiesMap &properties) {
389 VLOG(2) << __func__;
Darin Petkovbac96002011-08-09 13:22:00 -0700390 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Darin Petkovc5f56562011-08-06 16:40:05 -0700391 simple_proxy_->Connect(properties);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700392 SetState(kStateConnected);
Darin Petkovbac96002011-08-09 13:22:00 -0700393 EstablishLink();
394}
395
Darin Petkovfb0625e2012-01-16 13:05:56 +0100396void Cellular::Disconnect(Error *error) {
397 VLOG(2) << __func__;
398 if (state_ != kStateConnected &&
399 state_ != kStateLinked) {
400 Error::PopulateAndLog(
401 error, Error::kInProgress, "Not connected; request ignored.");
402 return;
403 }
404 // Defer because we may be in a dbus-c++ callback.
405 dispatcher()->PostTask(
406 task_factory_.NewRunnableMethod(&Cellular::DisconnectTask));
407}
408
409void Cellular::DisconnectTask() {
410 VLOG(2) << __func__;
411 DisconnectModem();
412}
413
414void Cellular::DisconnectModem() {
415 VLOG(2) << __func__;
416 if (state_ != kStateConnected &&
417 state_ != kStateLinked) {
418 return;
419 }
420 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583). Note,
421 // however, that this is invoked by the Stop method, so some extra refactoring
422 // may be needed to prevent the device instance from being destroyed before
423 // the modem manager calls are complete. Maybe Disconnect and Disable need to
424 // be handled by the parent Modem class.
425 try {
426 proxy_->Disconnect();
427 } catch (const DBus::Error e) {
428 LOG(WARNING) << "Disconnect failed: " << e.what();
429 }
430 SetState(kStateRegistered);
431}
432
Darin Petkovbac96002011-08-09 13:22:00 -0700433void Cellular::EstablishLink() {
434 VLOG(2) << __func__;
Darin Petkov0828f5f2011-08-11 10:18:52 -0700435 CHECK_EQ(kStateConnected, state_);
436 unsigned int flags = 0;
Paul Stewartac4ac002011-08-26 12:04:26 -0700437 if (manager()->device_info()->GetFlags(interface_index(), &flags) &&
Darin Petkov0828f5f2011-08-11 10:18:52 -0700438 (flags & IFF_UP) != 0) {
439 LinkEvent(flags, IFF_UP);
440 return;
441 }
442 // TODO(petkov): Provide a timeout for a failed link-up request.
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700443 rtnl_handler()->SetInterfaceFlags(interface_index(), IFF_UP, IFF_UP);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700444}
445
446void Cellular::LinkEvent(unsigned int flags, unsigned int change) {
447 Device::LinkEvent(flags, change);
448 if ((flags & IFF_UP) != 0 && state_ == kStateConnected) {
Paul Stewartac4ac002011-08-26 12:04:26 -0700449 LOG(INFO) << link_name() << " is up.";
Darin Petkov0828f5f2011-08-11 10:18:52 -0700450 SetState(kStateLinked);
Paul Stewartac4ac002011-08-26 12:04:26 -0700451 manager()->RegisterService(service_);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700452 // TODO(petkov): For GSM, remember the APN.
Paul Stewart2bf1d352011-12-06 15:02:55 -0800453 if (AcquireIPConfig()) {
Darin Petkov60b8c3b2011-08-25 11:03:20 -0700454 SelectService(service_);
455 SetServiceState(Service::kStateConfiguring);
456 } else {
457 LOG(ERROR) << "Unable to acquire DHCP config.";
458 }
Darin Petkov0828f5f2011-08-11 10:18:52 -0700459 } else if ((flags & IFF_UP) == 0 && state_ == kStateLinked) {
460 SetState(kStateConnected);
Darin Petkov2c377382012-01-11 11:40:43 +0100461 DestroyService();
Darin Petkov0828f5f2011-08-11 10:18:52 -0700462 }
Darin Petkovc5f56562011-08-06 16:40:05 -0700463}
464
mukesh agrawal1830fa12011-09-26 14:31:40 -0700465void Cellular::OnModemStateChanged(uint32 /*old_state*/,
466 uint32 /*new_state*/,
467 uint32 /*reason*/) {
Darin Petkovc5f56562011-08-06 16:40:05 -0700468 // TODO(petkov): Implement this.
469 NOTIMPLEMENTED();
470}
471
Darin Petkovae0c64e2011-11-15 15:50:27 +0100472void Cellular::OnModemManagerPropertiesChanged(
473 const DBusPropertiesMap &properties) {
Darin Petkov721ac932011-11-16 15:43:09 +0100474 capability_->OnModemManagerPropertiesChanged(properties);
Chris Masone889666b2011-07-03 12:58:50 -0700475}
476
Darin Petkovae0c64e2011-11-15 15:50:27 +0100477void Cellular::set_home_provider(const Operator &oper) {
478 home_provider_.CopyFrom(oper);
479}
480
Darin Petkovac635a82012-01-10 16:51:58 +0100481string Cellular::CreateFriendlyServiceName() {
482 VLOG(2) << __func__;
483 return capability_.get() ? capability_->CreateFriendlyServiceName() : "";
484}
485
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700486} // namespace shill