blob: 4dd3cd99775593ba692b7c9ccd5785f348a84188 [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 Shienbrood5de44ab2011-12-05 10:46:27 -050022const char CellularCapability::kConnectPropertyPhoneNumber[] = "number";
23const char CellularCapability::kPropertyIMSI[] = "imsi";
Eric Shienbrood9a245532012-03-07 14:20:39 -050024// All timeout values are in milliseconds
25const int CellularCapability::kTimeoutActivate = 120000;
26const int CellularCapability::kTimeoutConnect = 45000;
27const int CellularCapability::kTimeoutDefault = 5000;
28const int CellularCapability::kTimeoutEnable = 15000;
29const int CellularCapability::kTimeoutRegister = 90000;
30const int CellularCapability::kTimeoutScan = 120000;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050031
32CellularCapability::CellularCapability(Cellular *cellular,
33 ProxyFactory *proxy_factory)
34 : allow_roaming_(false),
Darin Petkov0d06f7d2012-02-03 13:08:19 +010035 scanning_supported_(false),
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050036 cellular_(cellular),
Eric Shienbrood9a245532012-03-07 14:20:39 -050037 proxy_factory_(proxy_factory),
38 weak_ptr_factory_(this) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050039 PropertyStore *store = cellular->mutable_store();
40 store->RegisterConstString(flimflam::kCarrierProperty, &carrier_);
Darin Petkov9c1dcef2012-02-07 15:58:26 +010041 HelpRegisterDerivedBool(flimflam::kCellularAllowRoamingProperty,
42 &CellularCapability::GetAllowRoaming,
43 &CellularCapability::SetAllowRoaming);
Darin Petkov0d06f7d2012-02-03 13:08:19 +010044 store->RegisterConstBool(flimflam::kSupportNetworkScanProperty,
45 &scanning_supported_);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050046 store->RegisterConstString(flimflam::kEsnProperty, &esn_);
47 store->RegisterConstString(flimflam::kFirmwareRevisionProperty,
48 &firmware_revision_);
49 store->RegisterConstString(flimflam::kHardwareRevisionProperty,
50 &hardware_revision_);
51 store->RegisterConstString(flimflam::kImeiProperty, &imei_);
52 store->RegisterConstString(flimflam::kImsiProperty, &imsi_);
53 store->RegisterConstString(flimflam::kManufacturerProperty, &manufacturer_);
54 store->RegisterConstString(flimflam::kMdnProperty, &mdn_);
55 store->RegisterConstString(flimflam::kMeidProperty, &meid_);
56 store->RegisterConstString(flimflam::kMinProperty, &min_);
57 store->RegisterConstString(flimflam::kModelIDProperty, &model_id_);
58}
Darin Petkovdaf43862011-10-27 11:37:28 +020059
60CellularCapability::~CellularCapability() {}
61
Darin Petkov9c1dcef2012-02-07 15:58:26 +010062void CellularCapability::HelpRegisterDerivedBool(
63 const string &name,
64 bool(CellularCapability::*get)(Error *error),
65 void(CellularCapability::*set)(const bool &value, Error *error)) {
66 cellular()->mutable_store()->RegisterDerivedBool(
67 name,
68 BoolAccessor(
69 new CustomAccessor<CellularCapability, bool>(this, get, set)));
70}
71
72void CellularCapability::SetAllowRoaming(const bool &value, Error */*error*/) {
73 VLOG(2) << __func__ << "(" << allow_roaming_ << "->" << value << ")";
74 if (allow_roaming_ == value) {
75 return;
76 }
77 allow_roaming_ = value;
78 if (!value && GetRoamingStateString() == flimflam::kRoamingStateRoaming) {
79 Error error;
80 cellular()->Disconnect(&error);
81 }
82 cellular()->adaptor()->EmitBoolChanged(
83 flimflam::kCellularAllowRoamingProperty, value);
84}
85
Eric Shienbrood9a245532012-03-07 14:20:39 -050086void CellularCapability::RunNextStep(CellularTaskList *tasks) {
87 CHECK(!tasks->empty());
88 VLOG(2) << __func__ << ": " << tasks->size() << " remaining tasks";
89 Closure task = (*tasks)[0];
90 tasks->erase(tasks->begin());
91 cellular()->dispatcher()->PostTask(task);
Darin Petkovb05315f2011-11-07 10:14:25 +010092}
93
Eric Shienbrood9a245532012-03-07 14:20:39 -050094void CellularCapability::StepCompletedCallback(
95 const ResultCallback &callback,
96 CellularTaskList *tasks,
97 const Error &error) {
98 if (error.IsSuccess() && !tasks->empty()) {
99 RunNextStep(tasks);
100 return;
101 }
102 delete tasks;
103 callback.Run(error);
104}
105
106void CellularCapability::InitProxies() {
107 VLOG(2) << __func__;
108 proxy_.reset(proxy_factory()->CreateModemProxy(
109 cellular()->dbus_path(), cellular()->dbus_owner()));
110 simple_proxy_.reset(proxy_factory()->CreateModemSimpleProxy(
111 cellular()->dbus_path(), cellular()->dbus_owner()));
112 proxy_->set_state_changed_callback(
113 Bind(&CellularCapability::OnModemStateChangedSignal,
114 weak_ptr_factory_.GetWeakPtr()));
115}
116
117void CellularCapability::ReleaseProxies() {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500118 VLOG(2) << __func__;
119 proxy_.reset();
120 simple_proxy_.reset();
Darin Petkova3d3be52011-11-14 21:34:16 +0100121}
122
Eric Shienbrood9a245532012-03-07 14:20:39 -0500123void CellularCapability::FinishEnable(const ResultCallback &callback) {
124 callback.Run(Error());
125 GetRegistrationState();
126 GetSignalQuality();
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500127}
128
Eric Shienbrood9a245532012-03-07 14:20:39 -0500129void CellularCapability::FinishDisable(const ResultCallback &callback) {
130 ReleaseProxies();
131 callback.Run(Error());
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500132}
133
134void CellularCapability::OnUnsupportedOperation(
135 const char *operation,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500136 Error *error) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500137 string message("The ");
138 message.append(operation).append(" operation is not supported.");
Eric Shienbrood9a245532012-03-07 14:20:39 -0500139 Error::PopulateAndLog(error, Error::kNotSupported, message);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500140}
141
Eric Shienbrood9a245532012-03-07 14:20:39 -0500142// always called from an async context
143void CellularCapability::EnableModem(const ResultCallback &callback) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500144 VLOG(2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500145 CHECK(!callback.is_null());
146 Error error;
147 proxy_->Enable(true, &error, callback, kTimeoutEnable);
148 if (error.IsFailure())
149 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500150}
151
Eric Shienbrood9a245532012-03-07 14:20:39 -0500152// always called from an async context
153void CellularCapability::DisableModem(const ResultCallback &callback) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500154 VLOG(2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500155 CHECK(!callback.is_null());
156 Error error;
157 proxy_->Enable(false, &error, callback, kTimeoutDefault);
158 if (error.IsFailure())
159 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500160}
161
Eric Shienbrood9a245532012-03-07 14:20:39 -0500162// always called from an async context
163void CellularCapability::GetModemStatus(const ResultCallback &callback) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500164 VLOG(2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500165 CHECK(!callback.is_null());
166 DBusPropertyMapCallback cb = Bind(&CellularCapability::OnGetModemStatusReply,
167 weak_ptr_factory_.GetWeakPtr(), callback);
168 Error error;
169 simple_proxy_->GetModemStatus(&error, cb, kTimeoutDefault);
170 if (error.IsFailure())
171 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500172}
173
Eric Shienbrood9a245532012-03-07 14:20:39 -0500174// always called from an async context
175void CellularCapability::GetModemInfo(const ResultCallback &callback) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500176 VLOG(2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500177 CHECK(!callback.is_null());
178 ModemInfoCallback cb = Bind(&CellularCapability::OnGetModemInfoReply,
179 weak_ptr_factory_.GetWeakPtr(), callback);
180 Error error;
181 proxy_->GetModemInfo(&error, cb, kTimeoutDefault);
182 if (error.IsFailure())
183 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500184}
185
Eric Shienbrood9a245532012-03-07 14:20:39 -0500186void CellularCapability::Connect(const DBusPropertiesMap &properties,
187 Error *error,
188 const ResultCallback &callback) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500189 VLOG(2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500190 ResultCallback cb = Bind(&CellularCapability::OnConnectReply,
191 weak_ptr_factory_.GetWeakPtr(),
192 callback);
193 simple_proxy_->Connect(properties, error, cb, kTimeoutConnect);
194}
195
196void CellularCapability::Disconnect(Error *error,
197 const ResultCallback &callback) {
198 VLOG(2) << __func__;
199 ResultCallback cb = Bind(&CellularCapability::OnDisconnectReply,
200 weak_ptr_factory_.GetWeakPtr(),
201 callback);
202 proxy_->Disconnect(error, cb, kTimeoutDefault);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500203}
204
205void CellularCapability::Activate(const string &/*carrier*/,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500206 Error *error,
207 const ResultCallback &/*callback*/) {
208 OnUnsupportedOperation(__func__, error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500209}
Darin Petkov184c54e2011-11-15 12:44:39 +0100210
211void CellularCapability::RegisterOnNetwork(
Eric Shienbrood9a245532012-03-07 14:20:39 -0500212 const string &/*network_id*/,
213 Error *error, const ResultCallback &/*callback*/) {
214 OnUnsupportedOperation(__func__, error);
Darin Petkov184c54e2011-11-15 12:44:39 +0100215}
216
Eric Shienbrood9a245532012-03-07 14:20:39 -0500217void CellularCapability::RequirePIN(const std::string &/*pin*/,
218 bool /*require*/,
219 Error *error,
220 const ResultCallback &/*callback*/) {
221 OnUnsupportedOperation(__func__, error);
Darin Petkovb05315f2011-11-07 10:14:25 +0100222}
223
Darin Petkove5bc2cb2011-12-07 14:47:32 +0100224void CellularCapability::EnterPIN(const string &/*pin*/,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500225 Error *error,
226 const ResultCallback &/*callback*/) {
227 OnUnsupportedOperation(__func__, error);
Darin Petkovb05315f2011-11-07 10:14:25 +0100228}
229
230void CellularCapability::UnblockPIN(const string &/*unblock_code*/,
231 const string &/*pin*/,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500232 Error *error,
233 const ResultCallback &/*callback*/) {
234 OnUnsupportedOperation(__func__, error);
Darin Petkovb05315f2011-11-07 10:14:25 +0100235}
236
237void CellularCapability::ChangePIN(const string &/*old_pin*/,
238 const string &/*new_pin*/,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500239 Error *error,
240 const ResultCallback &/*callback*/) {
241 OnUnsupportedOperation(__func__, error);
Darin Petkovb05315f2011-11-07 10:14:25 +0100242}
243
Eric Shienbrood9a245532012-03-07 14:20:39 -0500244void CellularCapability::Scan(Error *error,
245 const ResultCallback &callback) {
246 OnUnsupportedOperation(__func__, error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500247}
248
Eric Shienbrood9a245532012-03-07 14:20:39 -0500249void CellularCapability::OnGetModemStatusReply(
250 const ResultCallback &callback,
251 const DBusPropertiesMap &props,
252 const Error &error) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500253 VLOG(2) << __func__ << " " << props.size() << " props. error " << error;
254 if (error.IsSuccess()) {
255 DBusProperties::GetString(props, "carrier", &carrier_);
256 DBusProperties::GetString(props, "meid", &meid_);
257 DBusProperties::GetString(props, "imei", &imei_);
258 DBusProperties::GetString(props, kPropertyIMSI, &imsi_);
259 DBusProperties::GetString(props, "esn", &esn_);
260 DBusProperties::GetString(props, "mdn", &mdn_);
261 DBusProperties::GetString(props, "min", &min_);
262 DBusProperties::GetString(props, "firmware_revision", &firmware_revision_);
263
264 uint32 state;
265 if (DBusProperties::GetUint32(props, "state", &state))
266 cellular()->set_modem_state(static_cast<Cellular::ModemState>(state));
267
268 UpdateStatus(props);
269 }
Eric Shienbrood9a245532012-03-07 14:20:39 -0500270 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500271}
272
Eric Shienbrood9a245532012-03-07 14:20:39 -0500273void CellularCapability::OnGetModemInfoReply(
274 const ResultCallback &callback,
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500275 const ModemHardwareInfo &info,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500276 const Error &error) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500277 VLOG(2) << __func__ << "(" << error << ")";
278 if (error.IsSuccess()) {
279 manufacturer_ = info._1;
280 model_id_ = info._2;
281 hardware_revision_ = info._3;
282 VLOG(2) << __func__ << ": " << info._1 << ", " << info._2 << ", "
283 << info._3;
284 }
Eric Shienbrood9a245532012-03-07 14:20:39 -0500285 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500286}
287
Eric Shienbrood9a245532012-03-07 14:20:39 -0500288// TODO(ers): use the supplied callback when Connect is fully asynchronous
289void CellularCapability::OnConnectReply(const ResultCallback &callback,
290 const Error &error) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500291 VLOG(2) << __func__ << "(" << error << ")";
292 if (error.IsSuccess())
293 cellular()->OnConnected();
294 else
295 cellular()->OnConnectFailed();
Eric Shienbrood9a245532012-03-07 14:20:39 -0500296 if (!callback.is_null())
297 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500298}
299
Eric Shienbrood9a245532012-03-07 14:20:39 -0500300// TODO(ers): use the supplied callback when Disonnect is fully asynchronous
301void CellularCapability::OnDisconnectReply(const ResultCallback &callback,
302 const Error &error) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500303 VLOG(2) << __func__ << "(" << error << ")";
304 if (error.IsSuccess())
305 cellular()->OnDisconnected();
306 else
307 cellular()->OnDisconnectFailed();
Eric Shienbrood9a245532012-03-07 14:20:39 -0500308 if (!callback.is_null())
309 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500310}
311
Eric Shienbrood9a245532012-03-07 14:20:39 -0500312void CellularCapability::OnModemStateChangedSignal(
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500313 uint32 old_state, uint32 new_state, uint32 reason) {
314 VLOG(2) << __func__ << "(" << old_state << ", " << new_state << ", "
315 << reason << ")";
316 // TODO(petkov): Complete this (crosbug.com/19662)
317#if 0
318 modem_state_ = static_cast<ModemState>(new_state);
319 if (old_state == new_state) {
320 return;
321 }
322 switch (new_state) {
323 case kModemStateEnabled:
324 if (old_state == kModemStateDisabled ||
325 old_state == kModemStateEnabling) {
326 Start();
327 }
328 // TODO(petkov): Handle the case when the state is downgraded to Enabled.
329 break;
330 default:
331 break;
332 }
333#endif
Darin Petkov1272a432011-11-10 15:53:37 +0100334}
335
Darin Petkovdaf43862011-10-27 11:37:28 +0200336} // namespace shill