blob: 67bfbc950556c7659dbcfdc529d75e9039588889 [file] [log] [blame]
Jason Glasgow82f9ab32012-04-04 14:27:19 -04001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2// 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_classic.h"
6
7#include <base/bind.h>
8#include <chromeos/dbus/service_constants.h>
9
10#include "shill/cellular.h"
11#include "shill/error.h"
12#include "shill/property_accessor.h"
13#include "shill/proxy_factory.h"
Ben Chanfad4a0b2012-04-18 15:49:59 -070014#include "shill/scope_logger.h"
Jason Glasgow82f9ab32012-04-04 14:27:19 -040015
16using base::Bind;
17using base::Callback;
18using base::Closure;
19using std::string;
20
21namespace shill {
22
23const char CellularCapabilityClassic::kConnectPropertyApn[] = "apn";
24const char CellularCapabilityClassic::kConnectPropertyApnUsername[] =
25 "username";
26const char CellularCapabilityClassic::kConnectPropertyApnPassword[] =
27 "password";
28const char CellularCapabilityClassic::kConnectPropertyHomeOnly[] = "home_only";
29const char CellularCapabilityClassic::kConnectPropertyPhoneNumber[] = "number";
Eric Shienbrood7fce52c2012-04-13 19:11:02 -040030const char CellularCapabilityClassic::kModemPropertyEnabled[] = "Enabled";
31
32static Cellular::ModemState ConvertClassicToModemState(uint32 classic_state) {
33 ModemClassicState cstate =
34 static_cast<ModemClassicState>(classic_state);
35 switch (cstate) {
36 case kModemClassicStateUnknown:
37 return Cellular::kModemStateUnknown;
38 case kModemClassicStateDisabled:
39 return Cellular::kModemStateDisabled;
40 case kModemClassicStateDisabling:
41 return Cellular::kModemStateDisabling;
42 case kModemClassicStateEnabling:
43 return Cellular::kModemStateEnabling;
44 case kModemClassicStateEnabled:
45 return Cellular::kModemStateEnabled;
46 case kModemClassicStateSearching:
47 return Cellular::kModemStateSearching;
48 case kModemClassicStateRegistered:
49 return Cellular::kModemStateRegistered;
50 case kModemClassicStateDisconnecting:
51 return Cellular::kModemStateDisconnecting;
52 case kModemClassicStateConnecting:
53 return Cellular::kModemStateConnecting;
54 case kModemClassicStateConnected:
55 return Cellular::kModemStateConnected;
56 default:
57 return Cellular::kModemStateUnknown;
58 };
59}
Jason Glasgow82f9ab32012-04-04 14:27:19 -040060
61CellularCapabilityClassic::CellularCapabilityClassic(
62 Cellular *cellular,
63 ProxyFactory *proxy_factory)
64 : CellularCapability(cellular, proxy_factory),
65 weak_ptr_factory_(this) {
66 PropertyStore *store = cellular->mutable_store();
67 store->RegisterConstString(flimflam::kCarrierProperty, &carrier_);
68 store->RegisterConstBool(flimflam::kSupportNetworkScanProperty,
69 &scanning_supported_);
70 store->RegisterConstString(flimflam::kEsnProperty, &esn_);
71 store->RegisterConstString(flimflam::kFirmwareRevisionProperty,
72 &firmware_revision_);
73 store->RegisterConstString(flimflam::kHardwareRevisionProperty,
74 &hardware_revision_);
75 store->RegisterConstString(flimflam::kImeiProperty, &imei_);
76 store->RegisterConstString(flimflam::kImsiProperty, &imsi_);
77 store->RegisterConstString(flimflam::kManufacturerProperty, &manufacturer_);
78 store->RegisterConstString(flimflam::kMdnProperty, &mdn_);
79 store->RegisterConstString(flimflam::kMeidProperty, &meid_);
80 store->RegisterConstString(flimflam::kMinProperty, &min_);
81 store->RegisterConstString(flimflam::kModelIDProperty, &model_id_);
82}
83
84CellularCapabilityClassic::~CellularCapabilityClassic() {}
85
86void CellularCapabilityClassic::InitProxies() {
Ben Chanfad4a0b2012-04-18 15:49:59 -070087 SLOG(Cellular, 2) << __func__;
Jason Glasgow82f9ab32012-04-04 14:27:19 -040088 proxy_.reset(proxy_factory()->CreateModemProxy(
89 cellular()->dbus_path(), cellular()->dbus_owner()));
90 simple_proxy_.reset(proxy_factory()->CreateModemSimpleProxy(
91 cellular()->dbus_path(), cellular()->dbus_owner()));
92 proxy_->set_state_changed_callback(
93 Bind(&CellularCapabilityClassic::OnModemStateChangedSignal,
94 weak_ptr_factory_.GetWeakPtr()));
95}
96
97void CellularCapabilityClassic::ReleaseProxies() {
Ben Chanfad4a0b2012-04-18 15:49:59 -070098 SLOG(Cellular, 2) << __func__;
Jason Glasgow82f9ab32012-04-04 14:27:19 -040099 proxy_.reset();
100 simple_proxy_.reset();
101}
102
103void CellularCapabilityClassic::FinishEnable(const ResultCallback &callback) {
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400104 // Normally, running the callback is the last thing done in a method.
105 // In this case, we do it first, because we want to make sure that
106 // the device is marked as Enabled before the registration state is
107 // handled. See comment in Cellular::HandleNewRegistrationState.
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400108 callback.Run(Error());
109 GetRegistrationState();
110 GetSignalQuality();
111}
112
113void CellularCapabilityClassic::FinishDisable(const ResultCallback &callback) {
114 ReleaseProxies();
115 callback.Run(Error());
116}
117
118void CellularCapabilityClassic::OnUnsupportedOperation(
119 const char *operation,
120 Error *error) {
121 string message("The ");
122 message.append(operation).append(" operation is not supported.");
123 Error::PopulateAndLog(error, Error::kNotSupported, message);
124}
125
126// always called from an async context
127void CellularCapabilityClassic::EnableModem(const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700128 SLOG(Cellular, 2) << __func__;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400129 CHECK(!callback.is_null());
130 Error error;
131 proxy_->Enable(true, &error, callback, kTimeoutEnable);
132 if (error.IsFailure())
133 callback.Run(error);
134}
135
136// always called from an async context
137void CellularCapabilityClassic::DisableModem(const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700138 SLOG(Cellular, 2) << __func__;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400139 CHECK(!callback.is_null());
140 Error error;
141 proxy_->Enable(false, &error, callback, kTimeoutDefault);
142 if (error.IsFailure())
143 callback.Run(error);
144}
145
146// always called from an async context
147void CellularCapabilityClassic::GetModemStatus(const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700148 SLOG(Cellular, 2) << __func__;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400149 CHECK(!callback.is_null());
150 DBusPropertyMapCallback cb = Bind(
151 &CellularCapabilityClassic::OnGetModemStatusReply,
152 weak_ptr_factory_.GetWeakPtr(), callback);
153 Error error;
154 simple_proxy_->GetModemStatus(&error, cb, kTimeoutDefault);
155 if (error.IsFailure())
156 callback.Run(error);
157}
158
159// always called from an async context
160void CellularCapabilityClassic::GetModemInfo(const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700161 SLOG(Cellular, 2) << __func__;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400162 CHECK(!callback.is_null());
163 ModemInfoCallback cb = Bind(&CellularCapabilityClassic::OnGetModemInfoReply,
164 weak_ptr_factory_.GetWeakPtr(), callback);
165 Error error;
166 proxy_->GetModemInfo(&error, cb, kTimeoutDefault);
167 if (error.IsFailure())
168 callback.Run(error);
169}
170
171void CellularCapabilityClassic::StopModem(Error *error,
172 const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700173 SLOG(Cellular, 2) << __func__;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400174
175 CellularTaskList *tasks = new CellularTaskList();
176 ResultCallback cb =
177 Bind(&CellularCapabilityClassic::StepCompletedCallback,
178 weak_ptr_factory_.GetWeakPtr(), callback, false, tasks);
179 ResultCallback cb_ignore_error =
180 Bind(&CellularCapabilityClassic::StepCompletedCallback,
181 weak_ptr_factory_.GetWeakPtr(), callback, true, tasks);
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400182 // TODO(ers): We can skip the call to Disconnect if the modem has
183 // told us that the modem state is Disabled or Registered.
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400184 tasks->push_back(Bind(&CellularCapabilityClassic::Disconnect,
185 weak_ptr_factory_.GetWeakPtr(),
186 static_cast<Error *>(NULL), cb_ignore_error));
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400187 // TODO(ers): We can skip the call to Disable if the modem has
188 // told us that the modem state is Disabled.
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400189 tasks->push_back(Bind(&CellularCapabilityClassic::DisableModem,
190 weak_ptr_factory_.GetWeakPtr(), cb));
191 tasks->push_back(Bind(&CellularCapabilityClassic::FinishDisable,
192 weak_ptr_factory_.GetWeakPtr(), cb));
193
194 RunNextStep(tasks);
195}
196
197void CellularCapabilityClassic::Connect(const DBusPropertiesMap &properties,
198 Error *error,
199 const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700200 SLOG(Cellular, 2) << __func__;
Nathan Williamsb54974f2012-04-19 11:16:30 -0400201 simple_proxy_->Connect(properties, error, callback, kTimeoutConnect);
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400202}
203
204void CellularCapabilityClassic::Disconnect(Error *error,
205 const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700206 SLOG(Cellular, 2) << __func__;
Nathan Williamsb54974f2012-04-19 11:16:30 -0400207 proxy_->Disconnect(error, callback, kTimeoutDefault);
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400208}
209
210void CellularCapabilityClassic::Activate(const string &/*carrier*/,
211 Error *error,
212 const ResultCallback &/*callback*/) {
213 OnUnsupportedOperation(__func__, error);
214}
215
216void CellularCapabilityClassic::RegisterOnNetwork(
217 const string &/*network_id*/,
218 Error *error, const ResultCallback &/*callback*/) {
219 OnUnsupportedOperation(__func__, error);
220}
221
222void CellularCapabilityClassic::RequirePIN(const std::string &/*pin*/,
223 bool /*require*/,
224 Error *error,
225 const ResultCallback &/*callback*/) {
226 OnUnsupportedOperation(__func__, error);
227}
228
229void CellularCapabilityClassic::EnterPIN(const string &/*pin*/,
230 Error *error,
231 const ResultCallback &/*callback*/) {
232 OnUnsupportedOperation(__func__, error);
233}
234
235void CellularCapabilityClassic::UnblockPIN(const string &/*unblock_code*/,
236 const string &/*pin*/,
237 Error *error,
238 const ResultCallback &/*callback*/) {
239 OnUnsupportedOperation(__func__, error);
240}
241
242void CellularCapabilityClassic::ChangePIN(const string &/*old_pin*/,
243 const string &/*new_pin*/,
244 Error *error,
245 const ResultCallback &/*callback*/) {
246 OnUnsupportedOperation(__func__, error);
247}
248
249void CellularCapabilityClassic::Scan(Error *error,
250 const ResultCallback &callback) {
251 OnUnsupportedOperation(__func__, error);
252}
253
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400254void CellularCapabilityClassic::OnDBusPropertiesChanged(
255 const std::string &interface,
256 const DBusPropertiesMap &changed_properties,
257 const std::vector<std::string> &invalidated_properties) {
258 bool enabled;
259 // This solves a bootstrapping problem: If the modem is not yet
260 // enabled, there are no proxy objects associated with the capability
261 // object, so modem signals like StateChanged aren't seen. By monitoring
262 // changes to the Enabled property via the ModemManager, we're able to
263 // get the initialization process started, which will result in the
264 // creation of the proxy objects.
265 //
266 // The first time we see the change to Enabled (when the modem state
267 // is Unknown), we simply update the state, and rely on the Manager to
268 // enable the device when it is registered with the Manager. On subsequent
269 // changes to Enabled, we need to explicitly enable the device ourselves.
270 if (DBusProperties::GetBool(changed_properties,
271 kModemPropertyEnabled, &enabled)) {
272 Cellular::ModemState prev_modem_state = cellular()->modem_state();
273 if (enabled)
274 cellular()->set_modem_state(Cellular::kModemStateEnabled);
275 else
276 cellular()->set_modem_state(Cellular::kModemStateDisabled);
277 if (enabled && cellular()->state() == Cellular::kStateDisabled &&
278 prev_modem_state != Cellular::kModemStateUnknown &&
279 prev_modem_state != Cellular::kModemStateEnabled) {
280 cellular()->SetEnabled(true);
281 }
282 }
283}
284
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400285void CellularCapabilityClassic::OnGetModemStatusReply(
286 const ResultCallback &callback,
287 const DBusPropertiesMap &props,
288 const Error &error) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700289 SLOG(Cellular, 2) << __func__ << " " << props.size() << " props. error "
290 << error;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400291 if (error.IsSuccess()) {
292 DBusProperties::GetString(props, "carrier", &carrier_);
293 DBusProperties::GetString(props, "meid", &meid_);
294 DBusProperties::GetString(props, "imei", &imei_);
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400295 DBusProperties::GetString(props, kModemPropertyIMSI, &imsi_);
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400296 DBusProperties::GetString(props, "esn", &esn_);
297 DBusProperties::GetString(props, "mdn", &mdn_);
298 DBusProperties::GetString(props, "min", &min_);
299 DBusProperties::GetString(props, "firmware_revision", &firmware_revision_);
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400300 UpdateStatus(props);
301 }
302 callback.Run(error);
303}
304
305void CellularCapabilityClassic::OnGetModemInfoReply(
306 const ResultCallback &callback,
307 const ModemHardwareInfo &info,
308 const Error &error) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700309 SLOG(Cellular, 2) << __func__ << "(" << error << ")";
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400310 if (error.IsSuccess()) {
311 manufacturer_ = info._1;
312 model_id_ = info._2;
313 hardware_revision_ = info._3;
Ben Chanfad4a0b2012-04-18 15:49:59 -0700314 SLOG(Cellular, 2) << __func__ << ": " << info._1 << ", " << info._2 << ", "
315 << info._3;
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400316 }
317 callback.Run(error);
318}
319
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400320void CellularCapabilityClassic::OnModemStateChangedSignal(
321 uint32 old_state, uint32 new_state, uint32 reason) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700322 SLOG(Cellular, 2) << __func__ << "(" << old_state << ", " << new_state << ", "
323 << reason << ")";
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400324 cellular()->OnModemStateChanged(ConvertClassicToModemState(old_state),
325 ConvertClassicToModemState(new_state),
326 reason);
Jason Glasgow82f9ab32012-04-04 14:27:19 -0400327}
328
329} // namespace shill