blob: cda4eec15272689621e9ba5ce3f85dd432f81ab6 [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 Shienbrood5de44ab2011-12-05 10:46:27 -05007#include <chromeos/dbus/service_constants.h>
8
Darin Petkove5bc2cb2011-12-07 14:47:32 +01009#include "shill/adaptor_interfaces.h"
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 Shienbrood5de44ab2011-12-05 10:46:27 -050015using base::Callback;
Darin Petkovb05315f2011-11-07 10:14:25 +010016using std::string;
Darin Petkovdaf43862011-10-27 11:37:28 +020017
18namespace shill {
19
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050020const char CellularCapability::kConnectPropertyPhoneNumber[] = "number";
21const char CellularCapability::kPropertyIMSI[] = "imsi";
22const int CellularCapability::kTimeoutActivate = 120000; // ms
23const int CellularCapability::kTimeoutConnect = 45000; // ms
24const int CellularCapability::kTimeoutDefault = 5000; // ms
25const int CellularCapability::kTimeoutRegister = 90000; // ms
26const int CellularCapability::kTimeoutScan = 120000; // ms
27
28CellularCapability::MultiStepAsyncCallHandler::MultiStepAsyncCallHandler(
29 EventDispatcher *dispatcher)
30 : AsyncCallHandler(),
31 dispatcher_(dispatcher) {
32}
33
34CellularCapability::MultiStepAsyncCallHandler::~MultiStepAsyncCallHandler() {
35}
36
37void CellularCapability::MultiStepAsyncCallHandler::AddTask(Task *task) {
38 tasks_.push_back(task);
39}
40
41bool CellularCapability::MultiStepAsyncCallHandler::CompleteOperation() {
42 if (tasks_.empty()) {
43 DoReturn();
44 return true;
45 } else {
46 PostNextTask();
47 }
48 return false;
49}
50
51void CellularCapability::MultiStepAsyncCallHandler::PostNextTask() {
52 VLOG(2) << __func__ << ": " << tasks_.size() << " remaining actions";
53 if (tasks_.empty())
54 return;
55 Task *task = tasks_[0];
56 tasks_.weak_erase(tasks_.begin());
57 dispatcher_->PostTask(task);
58}
59
60CellularCapability::CellularCapability(Cellular *cellular,
61 ProxyFactory *proxy_factory)
62 : allow_roaming_(false),
Darin Petkov0d06f7d2012-02-03 13:08:19 +010063 scanning_supported_(false),
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050064 cellular_(cellular),
65 proxy_factory_(proxy_factory) {
66 PropertyStore *store = cellular->mutable_store();
67 store->RegisterConstString(flimflam::kCarrierProperty, &carrier_);
Darin Petkov9c1dcef2012-02-07 15:58:26 +010068 HelpRegisterDerivedBool(flimflam::kCellularAllowRoamingProperty,
69 &CellularCapability::GetAllowRoaming,
70 &CellularCapability::SetAllowRoaming);
Darin Petkov0d06f7d2012-02-03 13:08:19 +010071 store->RegisterConstBool(flimflam::kSupportNetworkScanProperty,
72 &scanning_supported_);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050073 store->RegisterConstString(flimflam::kEsnProperty, &esn_);
74 store->RegisterConstString(flimflam::kFirmwareRevisionProperty,
75 &firmware_revision_);
76 store->RegisterConstString(flimflam::kHardwareRevisionProperty,
77 &hardware_revision_);
78 store->RegisterConstString(flimflam::kImeiProperty, &imei_);
79 store->RegisterConstString(flimflam::kImsiProperty, &imsi_);
80 store->RegisterConstString(flimflam::kManufacturerProperty, &manufacturer_);
81 store->RegisterConstString(flimflam::kMdnProperty, &mdn_);
82 store->RegisterConstString(flimflam::kMeidProperty, &meid_);
83 store->RegisterConstString(flimflam::kMinProperty, &min_);
84 store->RegisterConstString(flimflam::kModelIDProperty, &model_id_);
85}
Darin Petkovdaf43862011-10-27 11:37:28 +020086
87CellularCapability::~CellularCapability() {}
88
Darin Petkov9c1dcef2012-02-07 15:58:26 +010089void CellularCapability::HelpRegisterDerivedBool(
90 const string &name,
91 bool(CellularCapability::*get)(Error *error),
92 void(CellularCapability::*set)(const bool &value, Error *error)) {
93 cellular()->mutable_store()->RegisterDerivedBool(
94 name,
95 BoolAccessor(
96 new CustomAccessor<CellularCapability, bool>(this, get, set)));
97}
98
99void CellularCapability::SetAllowRoaming(const bool &value, Error */*error*/) {
100 VLOG(2) << __func__ << "(" << allow_roaming_ << "->" << value << ")";
101 if (allow_roaming_ == value) {
102 return;
103 }
104 allow_roaming_ = value;
105 if (!value && GetRoamingStateString() == flimflam::kRoamingStateRoaming) {
106 Error error;
107 cellular()->Disconnect(&error);
108 }
109 cellular()->adaptor()->EmitBoolChanged(
110 flimflam::kCellularAllowRoamingProperty, value);
111}
112
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500113void CellularCapability::StartModem() {
114 VLOG(2) << __func__;
115 proxy_.reset(proxy_factory()->CreateModemProxy(
116 this, cellular()->dbus_path(), cellular()->dbus_owner()));
117 simple_proxy_.reset(proxy_factory()->CreateModemSimpleProxy(
118 this, cellular()->dbus_path(), cellular()->dbus_owner()));
Darin Petkovb05315f2011-11-07 10:14:25 +0100119}
120
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500121void CellularCapability::StopModem() {
122 VLOG(2) << __func__;
123 proxy_.reset();
124 simple_proxy_.reset();
Darin Petkova3d3be52011-11-14 21:34:16 +0100125}
126
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500127void CellularCapability::CompleteOperation(AsyncCallHandler *reply_handler) {
128 if (reply_handler && reply_handler->Complete())
129 delete reply_handler;
130}
131
132void CellularCapability::CompleteOperation(AsyncCallHandler *reply_handler,
133 const Error &error) {
134 if (reply_handler && reply_handler->Complete(error))
135 delete reply_handler;
136}
137
138void CellularCapability::OnUnsupportedOperation(
139 const char *operation,
140 AsyncCallHandler *call_handler) {
141 Error error;
142 string message("The ");
143 message.append(operation).append(" operation is not supported.");
144 Error::PopulateAndLog(&error, Error::kNotSupported, message);
145 CompleteOperation(call_handler, error);
146}
147
148void CellularCapability::EnableModem(AsyncCallHandler *call_handler) {
149 VLOG(2) << __func__;
150 proxy_->Enable(true, call_handler, kTimeoutDefault);
151}
152
153// TODO(ers): convert to async once we have a way for the callback
154// to distinguish an enable from a disable, and once the Stop() operation
155// has been converted to multi-step async.
156void CellularCapability::DisableModem(AsyncCallHandler * /*call_handler*/) {
157 try {
Jason Glasgowe9089492012-02-23 17:57:37 -0500158 if (proxy_.get()) {
159 proxy_->Enable(false);
160 }
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500161 cellular()->OnModemDisabled();
162 } catch (const DBus::Error e) {
163 LOG(WARNING) << "Disable failed: " << e.what();
164 }
165}
166
167void CellularCapability::GetModemStatus(AsyncCallHandler *call_handler) {
168 VLOG(2) << __func__;
169 simple_proxy_->GetModemStatus(call_handler, kTimeoutDefault);
170}
171
172void CellularCapability::GetModemInfo(AsyncCallHandler *call_handler) {
173 VLOG(2) << __func__;
174 proxy_->GetModemInfo(call_handler, kTimeoutDefault);
175}
176
177// TODO(ers): make this async (supply an AsyncCallHandler arg)
178void CellularCapability::Connect(const DBusPropertiesMap &properties) {
179 VLOG(2) << __func__;
180 simple_proxy_->Connect(properties, NULL, kTimeoutConnect);
181}
182
183// TODO(ers): convert to async once the Stop() operation
184// has been converted to multi-step async.
185void CellularCapability::Disconnect() {
186 VLOG(2) << __func__;
187 try {
188 proxy_->Disconnect();
189 cellular()->OnDisconnected();
190 } catch (const DBus::Error e) {
191 LOG(WARNING) << "Disconnect failed: " << e.what();
192 }
193}
194
195void CellularCapability::Activate(const string &/*carrier*/,
196 AsyncCallHandler *call_handler) {
197 OnUnsupportedOperation(__func__, call_handler);
198}
Darin Petkov184c54e2011-11-15 12:44:39 +0100199
200void CellularCapability::RegisterOnNetwork(
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500201 const string &/*network_id*/, AsyncCallHandler *call_handler) {
202 OnUnsupportedOperation(__func__, call_handler);
Darin Petkov184c54e2011-11-15 12:44:39 +0100203}
204
Darin Petkovc64fe5e2012-01-11 12:46:13 +0100205void CellularCapability::RequirePIN(
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500206 const string &/*pin*/, bool /*require*/, AsyncCallHandler *call_handler) {
207 OnUnsupportedOperation(__func__, call_handler);
Darin Petkovb05315f2011-11-07 10:14:25 +0100208}
209
Darin Petkove5bc2cb2011-12-07 14:47:32 +0100210void CellularCapability::EnterPIN(const string &/*pin*/,
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500211 AsyncCallHandler *call_handler) {
212 OnUnsupportedOperation(__func__, call_handler);
Darin Petkovb05315f2011-11-07 10:14:25 +0100213}
214
215void CellularCapability::UnblockPIN(const string &/*unblock_code*/,
216 const string &/*pin*/,
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500217 AsyncCallHandler *call_handler) {
218 OnUnsupportedOperation(__func__, call_handler);
Darin Petkovb05315f2011-11-07 10:14:25 +0100219}
220
221void CellularCapability::ChangePIN(const string &/*old_pin*/,
222 const string &/*new_pin*/,
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500223 AsyncCallHandler *call_handler) {
224 OnUnsupportedOperation(__func__, call_handler);
Darin Petkovb05315f2011-11-07 10:14:25 +0100225}
226
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500227void CellularCapability::Scan(AsyncCallHandler *call_handler) {
228 OnUnsupportedOperation(__func__, call_handler);
229}
230
231void CellularCapability::OnModemEnableCallback(const Error &error,
232 AsyncCallHandler *call_handler) {
233 VLOG(2) << __func__ << "(" << error << ")";
234 if (error.IsSuccess())
235 cellular()->OnModemEnabled();
236 CompleteOperation(call_handler, error);
237}
238
239void CellularCapability::OnGetModemStatusCallback(
240 const DBusPropertiesMap &props, const Error &error,
241 AsyncCallHandler *call_handler) {
242 VLOG(2) << __func__ << " " << props.size() << " props. error " << error;
243 if (error.IsSuccess()) {
244 DBusProperties::GetString(props, "carrier", &carrier_);
245 DBusProperties::GetString(props, "meid", &meid_);
246 DBusProperties::GetString(props, "imei", &imei_);
247 DBusProperties::GetString(props, kPropertyIMSI, &imsi_);
248 DBusProperties::GetString(props, "esn", &esn_);
249 DBusProperties::GetString(props, "mdn", &mdn_);
250 DBusProperties::GetString(props, "min", &min_);
251 DBusProperties::GetString(props, "firmware_revision", &firmware_revision_);
252
253 uint32 state;
254 if (DBusProperties::GetUint32(props, "state", &state))
255 cellular()->set_modem_state(static_cast<Cellular::ModemState>(state));
256
257 UpdateStatus(props);
258 }
259 CompleteOperation(call_handler, error);
260}
261
262void CellularCapability::OnGetModemInfoCallback(
263 const ModemHardwareInfo &info,
264 const Error &error,
265 AsyncCallHandler *call_handler) {
266 VLOG(2) << __func__ << "(" << error << ")";
267 if (error.IsSuccess()) {
268 manufacturer_ = info._1;
269 model_id_ = info._2;
270 hardware_revision_ = info._3;
271 VLOG(2) << __func__ << ": " << info._1 << ", " << info._2 << ", "
272 << info._3;
273 }
274 CompleteOperation(call_handler, error);
275}
276
277void CellularCapability::OnConnectCallback(const Error &error,
278 AsyncCallHandler *call_handler) {
279 VLOG(2) << __func__ << "(" << error << ")";
280 if (error.IsSuccess())
281 cellular()->OnConnected();
282 else
283 cellular()->OnConnectFailed();
284 CompleteOperation(call_handler, error);
285}
286
287void CellularCapability::OnDisconnectCallback(const Error &error,
288 AsyncCallHandler *call_handler) {
289 VLOG(2) << __func__ << "(" << error << ")";
290 if (error.IsSuccess())
291 cellular()->OnDisconnected();
292 else
293 cellular()->OnDisconnectFailed();
294 CompleteOperation(call_handler, error);
295}
296
297void CellularCapability::OnModemStateChanged(
298 uint32 old_state, uint32 new_state, uint32 reason) {
299 VLOG(2) << __func__ << "(" << old_state << ", " << new_state << ", "
300 << reason << ")";
301 // TODO(petkov): Complete this (crosbug.com/19662)
302#if 0
303 modem_state_ = static_cast<ModemState>(new_state);
304 if (old_state == new_state) {
305 return;
306 }
307 switch (new_state) {
308 case kModemStateEnabled:
309 if (old_state == kModemStateDisabled ||
310 old_state == kModemStateEnabling) {
311 Start();
312 }
313 // TODO(petkov): Handle the case when the state is downgraded to Enabled.
314 break;
315 default:
316 break;
317 }
318#endif
Darin Petkov1272a432011-11-10 15:53:37 +0100319}
320
Darin Petkovdaf43862011-10-27 11:37:28 +0200321} // namespace shill