blob: f5d7630815d3fae38594705552d4ba0e9c746efd [file] [log] [blame]
Eric Shienbrood5de44ab2011-12-05 10:46:27 -05001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Darin Petkovdaf43862011-10-27 11:37:28 +02002// 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_capability.h"
6
Eric Shienbrood9a245532012-03-07 14:20:39 -05007#include <base/bind.h>
Eric Shienbrood5de44ab2011-12-05 10:46:27 -05008#include <chromeos/dbus/service_constants.h>
9
Darin Petkovdaf43862011-10-27 11:37:28 +020010#include "shill/cellular.h"
Darin Petkovb05315f2011-11-07 10:14:25 +010011#include "shill/error.h"
Darin Petkov9c1dcef2012-02-07 15:58:26 +010012#include "shill/property_accessor.h"
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050013#include "shill/proxy_factory.h"
Darin Petkovb05315f2011-11-07 10:14:25 +010014
Eric Shienbrood9a245532012-03-07 14:20:39 -050015using base::Bind;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050016using base::Callback;
Eric Shienbrood3e20a232012-02-16 11:35:56 -050017using base::Closure;
Darin Petkovb05315f2011-11-07 10:14:25 +010018using std::string;
Darin Petkovdaf43862011-10-27 11:37:28 +020019
20namespace shill {
21
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -040022const char CellularCapability::kConnectPropertyApn[] = "apn";
23const char CellularCapability::kConnectPropertyApnUsername[] = "username";
24const char CellularCapability::kConnectPropertyApnPassword[] = "password";
25const char CellularCapability::kConnectPropertyHomeOnly[] = "home_only";
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050026const char CellularCapability::kConnectPropertyPhoneNumber[] = "number";
27const char CellularCapability::kPropertyIMSI[] = "imsi";
Eric Shienbrood9a245532012-03-07 14:20:39 -050028// All timeout values are in milliseconds
29const int CellularCapability::kTimeoutActivate = 120000;
30const int CellularCapability::kTimeoutConnect = 45000;
31const int CellularCapability::kTimeoutDefault = 5000;
32const int CellularCapability::kTimeoutEnable = 15000;
33const int CellularCapability::kTimeoutRegister = 90000;
34const int CellularCapability::kTimeoutScan = 120000;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050035
36CellularCapability::CellularCapability(Cellular *cellular,
37 ProxyFactory *proxy_factory)
38 : allow_roaming_(false),
Darin Petkov0d06f7d2012-02-03 13:08:19 +010039 scanning_supported_(false),
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050040 cellular_(cellular),
Eric Shienbrood9a245532012-03-07 14:20:39 -050041 proxy_factory_(proxy_factory),
42 weak_ptr_factory_(this) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050043 PropertyStore *store = cellular->mutable_store();
44 store->RegisterConstString(flimflam::kCarrierProperty, &carrier_);
Darin Petkov9c1dcef2012-02-07 15:58:26 +010045 HelpRegisterDerivedBool(flimflam::kCellularAllowRoamingProperty,
46 &CellularCapability::GetAllowRoaming,
47 &CellularCapability::SetAllowRoaming);
Darin Petkov0d06f7d2012-02-03 13:08:19 +010048 store->RegisterConstBool(flimflam::kSupportNetworkScanProperty,
49 &scanning_supported_);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050050 store->RegisterConstString(flimflam::kEsnProperty, &esn_);
51 store->RegisterConstString(flimflam::kFirmwareRevisionProperty,
52 &firmware_revision_);
53 store->RegisterConstString(flimflam::kHardwareRevisionProperty,
54 &hardware_revision_);
55 store->RegisterConstString(flimflam::kImeiProperty, &imei_);
56 store->RegisterConstString(flimflam::kImsiProperty, &imsi_);
57 store->RegisterConstString(flimflam::kManufacturerProperty, &manufacturer_);
58 store->RegisterConstString(flimflam::kMdnProperty, &mdn_);
59 store->RegisterConstString(flimflam::kMeidProperty, &meid_);
60 store->RegisterConstString(flimflam::kMinProperty, &min_);
61 store->RegisterConstString(flimflam::kModelIDProperty, &model_id_);
62}
Darin Petkovdaf43862011-10-27 11:37:28 +020063
64CellularCapability::~CellularCapability() {}
65
Darin Petkov9c1dcef2012-02-07 15:58:26 +010066void CellularCapability::HelpRegisterDerivedBool(
67 const string &name,
68 bool(CellularCapability::*get)(Error *error),
69 void(CellularCapability::*set)(const bool &value, Error *error)) {
70 cellular()->mutable_store()->RegisterDerivedBool(
71 name,
72 BoolAccessor(
73 new CustomAccessor<CellularCapability, bool>(this, get, set)));
74}
75
76void CellularCapability::SetAllowRoaming(const bool &value, Error */*error*/) {
77 VLOG(2) << __func__ << "(" << allow_roaming_ << "->" << value << ")";
78 if (allow_roaming_ == value) {
79 return;
80 }
81 allow_roaming_ = value;
82 if (!value && GetRoamingStateString() == flimflam::kRoamingStateRoaming) {
83 Error error;
84 cellular()->Disconnect(&error);
85 }
86 cellular()->adaptor()->EmitBoolChanged(
87 flimflam::kCellularAllowRoamingProperty, value);
88}
89
Eric Shienbrood9a245532012-03-07 14:20:39 -050090void CellularCapability::RunNextStep(CellularTaskList *tasks) {
91 CHECK(!tasks->empty());
92 VLOG(2) << __func__ << ": " << tasks->size() << " remaining tasks";
93 Closure task = (*tasks)[0];
94 tasks->erase(tasks->begin());
95 cellular()->dispatcher()->PostTask(task);
Darin Petkovb05315f2011-11-07 10:14:25 +010096}
97
Eric Shienbrood9a245532012-03-07 14:20:39 -050098void CellularCapability::StepCompletedCallback(
99 const ResultCallback &callback,
Thieu Le923006b2012-04-05 16:32:58 -0700100 bool ignore_error,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500101 CellularTaskList *tasks,
102 const Error &error) {
Thieu Le923006b2012-04-05 16:32:58 -0700103 if ((ignore_error || error.IsSuccess()) && !tasks->empty()) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500104 RunNextStep(tasks);
105 return;
106 }
107 delete tasks;
108 callback.Run(error);
109}
110
111void CellularCapability::InitProxies() {
112 VLOG(2) << __func__;
113 proxy_.reset(proxy_factory()->CreateModemProxy(
114 cellular()->dbus_path(), cellular()->dbus_owner()));
115 simple_proxy_.reset(proxy_factory()->CreateModemSimpleProxy(
116 cellular()->dbus_path(), cellular()->dbus_owner()));
117 proxy_->set_state_changed_callback(
118 Bind(&CellularCapability::OnModemStateChangedSignal,
119 weak_ptr_factory_.GetWeakPtr()));
120}
121
122void CellularCapability::ReleaseProxies() {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500123 VLOG(2) << __func__;
124 proxy_.reset();
125 simple_proxy_.reset();
Darin Petkova3d3be52011-11-14 21:34:16 +0100126}
127
Eric Shienbrood9a245532012-03-07 14:20:39 -0500128void CellularCapability::FinishEnable(const ResultCallback &callback) {
129 callback.Run(Error());
130 GetRegistrationState();
131 GetSignalQuality();
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500132}
133
Eric Shienbrood9a245532012-03-07 14:20:39 -0500134void CellularCapability::FinishDisable(const ResultCallback &callback) {
135 ReleaseProxies();
136 callback.Run(Error());
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500137}
138
139void CellularCapability::OnUnsupportedOperation(
140 const char *operation,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500141 Error *error) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500142 string message("The ");
143 message.append(operation).append(" operation is not supported.");
Eric Shienbrood9a245532012-03-07 14:20:39 -0500144 Error::PopulateAndLog(error, Error::kNotSupported, message);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500145}
146
Eric Shienbrood9a245532012-03-07 14:20:39 -0500147// always called from an async context
148void CellularCapability::EnableModem(const ResultCallback &callback) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500149 VLOG(2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500150 CHECK(!callback.is_null());
151 Error error;
152 proxy_->Enable(true, &error, callback, kTimeoutEnable);
153 if (error.IsFailure())
154 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500155}
156
Eric Shienbrood9a245532012-03-07 14:20:39 -0500157// always called from an async context
158void CellularCapability::DisableModem(const ResultCallback &callback) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500159 VLOG(2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500160 CHECK(!callback.is_null());
161 Error error;
162 proxy_->Enable(false, &error, callback, kTimeoutDefault);
163 if (error.IsFailure())
164 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500165}
166
Eric Shienbrood9a245532012-03-07 14:20:39 -0500167// always called from an async context
168void CellularCapability::GetModemStatus(const ResultCallback &callback) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500169 VLOG(2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500170 CHECK(!callback.is_null());
171 DBusPropertyMapCallback cb = Bind(&CellularCapability::OnGetModemStatusReply,
172 weak_ptr_factory_.GetWeakPtr(), callback);
173 Error error;
174 simple_proxy_->GetModemStatus(&error, cb, kTimeoutDefault);
175 if (error.IsFailure())
176 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500177}
178
Eric Shienbrood9a245532012-03-07 14:20:39 -0500179// always called from an async context
180void CellularCapability::GetModemInfo(const ResultCallback &callback) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500181 VLOG(2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500182 CHECK(!callback.is_null());
183 ModemInfoCallback cb = Bind(&CellularCapability::OnGetModemInfoReply,
184 weak_ptr_factory_.GetWeakPtr(), callback);
185 Error error;
186 proxy_->GetModemInfo(&error, cb, kTimeoutDefault);
187 if (error.IsFailure())
188 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500189}
190
Thieu Le923006b2012-04-05 16:32:58 -0700191void CellularCapability::StopModem(Error *error,
192 const ResultCallback &callback) {
193 VLOG(2) << __func__;
194
195 CellularTaskList *tasks = new CellularTaskList();
196 ResultCallback cb =
197 Bind(&CellularCapability::StepCompletedCallback,
198 weak_ptr_factory_.GetWeakPtr(), callback, false, tasks);
199 ResultCallback cb_ignore_error =
200 Bind(&CellularCapability::StepCompletedCallback,
201 weak_ptr_factory_.GetWeakPtr(), callback, true, tasks);
202 tasks->push_back(Bind(&CellularCapability::Disconnect,
203 weak_ptr_factory_.GetWeakPtr(),
204 static_cast<Error *>(NULL), cb_ignore_error));
205 tasks->push_back(Bind(&CellularCapability::DisableModem,
206 weak_ptr_factory_.GetWeakPtr(), cb));
207 tasks->push_back(Bind(&CellularCapability::FinishDisable,
208 weak_ptr_factory_.GetWeakPtr(), cb));
209
210 RunNextStep(tasks);
211}
212
Eric Shienbrood9a245532012-03-07 14:20:39 -0500213void CellularCapability::Connect(const DBusPropertiesMap &properties,
214 Error *error,
215 const ResultCallback &callback) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500216 VLOG(2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500217 ResultCallback cb = Bind(&CellularCapability::OnConnectReply,
218 weak_ptr_factory_.GetWeakPtr(),
219 callback);
220 simple_proxy_->Connect(properties, error, cb, kTimeoutConnect);
221}
222
223void CellularCapability::Disconnect(Error *error,
224 const ResultCallback &callback) {
225 VLOG(2) << __func__;
226 ResultCallback cb = Bind(&CellularCapability::OnDisconnectReply,
227 weak_ptr_factory_.GetWeakPtr(),
228 callback);
229 proxy_->Disconnect(error, cb, kTimeoutDefault);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500230}
231
232void CellularCapability::Activate(const string &/*carrier*/,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500233 Error *error,
234 const ResultCallback &/*callback*/) {
235 OnUnsupportedOperation(__func__, error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500236}
Darin Petkov184c54e2011-11-15 12:44:39 +0100237
238void CellularCapability::RegisterOnNetwork(
Eric Shienbrood9a245532012-03-07 14:20:39 -0500239 const string &/*network_id*/,
240 Error *error, const ResultCallback &/*callback*/) {
241 OnUnsupportedOperation(__func__, error);
Darin Petkov184c54e2011-11-15 12:44:39 +0100242}
243
Eric Shienbrood9a245532012-03-07 14:20:39 -0500244void CellularCapability::RequirePIN(const std::string &/*pin*/,
245 bool /*require*/,
246 Error *error,
247 const ResultCallback &/*callback*/) {
248 OnUnsupportedOperation(__func__, error);
Darin Petkovb05315f2011-11-07 10:14:25 +0100249}
250
Darin Petkove5bc2cb2011-12-07 14:47:32 +0100251void CellularCapability::EnterPIN(const string &/*pin*/,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500252 Error *error,
253 const ResultCallback &/*callback*/) {
254 OnUnsupportedOperation(__func__, error);
Darin Petkovb05315f2011-11-07 10:14:25 +0100255}
256
257void CellularCapability::UnblockPIN(const string &/*unblock_code*/,
258 const string &/*pin*/,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500259 Error *error,
260 const ResultCallback &/*callback*/) {
261 OnUnsupportedOperation(__func__, error);
Darin Petkovb05315f2011-11-07 10:14:25 +0100262}
263
264void CellularCapability::ChangePIN(const string &/*old_pin*/,
265 const string &/*new_pin*/,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500266 Error *error,
267 const ResultCallback &/*callback*/) {
268 OnUnsupportedOperation(__func__, error);
Darin Petkovb05315f2011-11-07 10:14:25 +0100269}
270
Eric Shienbrood9a245532012-03-07 14:20:39 -0500271void CellularCapability::Scan(Error *error,
272 const ResultCallback &callback) {
273 OnUnsupportedOperation(__func__, error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500274}
275
Eric Shienbrood9a245532012-03-07 14:20:39 -0500276void CellularCapability::OnGetModemStatusReply(
277 const ResultCallback &callback,
278 const DBusPropertiesMap &props,
279 const Error &error) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500280 VLOG(2) << __func__ << " " << props.size() << " props. error " << error;
281 if (error.IsSuccess()) {
282 DBusProperties::GetString(props, "carrier", &carrier_);
283 DBusProperties::GetString(props, "meid", &meid_);
284 DBusProperties::GetString(props, "imei", &imei_);
285 DBusProperties::GetString(props, kPropertyIMSI, &imsi_);
286 DBusProperties::GetString(props, "esn", &esn_);
287 DBusProperties::GetString(props, "mdn", &mdn_);
288 DBusProperties::GetString(props, "min", &min_);
289 DBusProperties::GetString(props, "firmware_revision", &firmware_revision_);
290
291 uint32 state;
292 if (DBusProperties::GetUint32(props, "state", &state))
293 cellular()->set_modem_state(static_cast<Cellular::ModemState>(state));
294
295 UpdateStatus(props);
296 }
Eric Shienbrood9a245532012-03-07 14:20:39 -0500297 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500298}
299
Eric Shienbrood9a245532012-03-07 14:20:39 -0500300void CellularCapability::OnGetModemInfoReply(
301 const ResultCallback &callback,
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500302 const ModemHardwareInfo &info,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500303 const Error &error) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500304 VLOG(2) << __func__ << "(" << error << ")";
305 if (error.IsSuccess()) {
306 manufacturer_ = info._1;
307 model_id_ = info._2;
308 hardware_revision_ = info._3;
309 VLOG(2) << __func__ << ": " << info._1 << ", " << info._2 << ", "
310 << info._3;
311 }
Eric Shienbrood9a245532012-03-07 14:20:39 -0500312 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500313}
314
Eric Shienbrood9a245532012-03-07 14:20:39 -0500315// TODO(ers): use the supplied callback when Connect is fully asynchronous
316void CellularCapability::OnConnectReply(const ResultCallback &callback,
317 const Error &error) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500318 VLOG(2) << __func__ << "(" << error << ")";
319 if (error.IsSuccess())
320 cellular()->OnConnected();
321 else
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400322 cellular()->OnConnectFailed(error);
Eric Shienbrood9a245532012-03-07 14:20:39 -0500323 if (!callback.is_null())
324 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500325}
326
Eric Shienbrood9a245532012-03-07 14:20:39 -0500327// TODO(ers): use the supplied callback when Disonnect is fully asynchronous
328void CellularCapability::OnDisconnectReply(const ResultCallback &callback,
329 const Error &error) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500330 VLOG(2) << __func__ << "(" << error << ")";
331 if (error.IsSuccess())
332 cellular()->OnDisconnected();
333 else
334 cellular()->OnDisconnectFailed();
Eric Shienbrood9a245532012-03-07 14:20:39 -0500335 if (!callback.is_null())
336 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500337}
338
Eric Shienbrood9a245532012-03-07 14:20:39 -0500339void CellularCapability::OnModemStateChangedSignal(
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500340 uint32 old_state, uint32 new_state, uint32 reason) {
341 VLOG(2) << __func__ << "(" << old_state << ", " << new_state << ", "
342 << reason << ")";
343 // TODO(petkov): Complete this (crosbug.com/19662)
344#if 0
345 modem_state_ = static_cast<ModemState>(new_state);
346 if (old_state == new_state) {
347 return;
348 }
349 switch (new_state) {
350 case kModemStateEnabled:
351 if (old_state == kModemStateDisabled ||
352 old_state == kModemStateEnabling) {
353 Start();
354 }
355 // TODO(petkov): Handle the case when the state is downgraded to Enabled.
356 break;
357 default:
358 break;
359 }
360#endif
Darin Petkov1272a432011-11-10 15:53:37 +0100361}
362
Darin Petkovdaf43862011-10-27 11:37:28 +0200363} // namespace shill