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