blob: 31dc5d82446227995c3668bb748de41b2a40dff7 [file] [log] [blame]
Darin Petkovac635a82012-01-10 16:51:58 +01001// 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_cdma.h"
6
Jason Glasgow4c0724a2012-04-17 15:47:40 -04007#include <string>
8#include <vector>
9
Eric Shienbrood3e20a232012-02-16 11:35:56 -050010#include <base/bind.h>
Darin Petkovac635a82012-01-10 16:51:58 +010011#include <base/stringprintf.h>
Darin Petkov20c13ec2011-11-09 15:07:15 +010012#include <chromeos/dbus/service_constants.h>
13#include <mm/mm-modem.h>
Darin Petkovdaf43862011-10-27 11:37:28 +020014
15#include "shill/cellular.h"
Darin Petkov184c54e2011-11-15 12:44:39 +010016#include "shill/cellular_service.h"
Christopher Wileyb691efd2012-08-09 13:51:51 -070017#include "shill/logging.h"
Darin Petkovdaf43862011-10-27 11:37:28 +020018#include "shill/proxy_factory.h"
19
Eric Shienbrood3e20a232012-02-16 11:35:56 -050020using base::Bind;
Darin Petkov20c13ec2011-11-09 15:07:15 +010021using std::string;
Jason Glasgow4c0724a2012-04-17 15:47:40 -040022using std::vector;
Darin Petkov20c13ec2011-11-09 15:07:15 +010023
Darin Petkovdaf43862011-10-27 11:37:28 +020024namespace shill {
25
Darin Petkovac635a82012-01-10 16:51:58 +010026// static
27unsigned int CellularCapabilityCDMA::friendly_service_name_id_ = 0;
28
Darin Petkovae0c64e2011-11-15 15:50:27 +010029const char CellularCapabilityCDMA::kPhoneNumber[] = "#777";
30
Eric Shienbrood5de44ab2011-12-05 10:46:27 -050031CellularCapabilityCDMA::CellularCapabilityCDMA(Cellular *cellular,
32 ProxyFactory *proxy_factory)
Jason Glasgow82f9ab32012-04-04 14:27:19 -040033 : CellularCapabilityClassic(cellular, proxy_factory),
Eric Shienbrood3e20a232012-02-16 11:35:56 -050034 weak_ptr_factory_(this),
Darin Petkovae0c64e2011-11-15 15:50:27 +010035 activation_state_(MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED),
Darin Petkov184c54e2011-11-15 12:44:39 +010036 registration_state_evdo_(MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN),
Darin Petkovae0c64e2011-11-15 15:50:27 +010037 registration_state_1x_(MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN),
38 prl_version_(0) {
Ben Chanfad4a0b2012-04-18 15:49:59 -070039 SLOG(Cellular, 2) << "Cellular capability constructed: CDMA";
Darin Petkovae0c64e2011-11-15 15:50:27 +010040 PropertyStore *store = cellular->mutable_store();
41 store->RegisterConstUint16(flimflam::kPRLVersionProperty, &prl_version_);
42}
Darin Petkovdaf43862011-10-27 11:37:28 +020043
Eric Shienbrood9a245532012-03-07 14:20:39 -050044void CellularCapabilityCDMA::InitProxies() {
Jason Glasgow82f9ab32012-04-04 14:27:19 -040045 CellularCapabilityClassic::InitProxies();
Darin Petkov184c54e2011-11-15 12:44:39 +010046 proxy_.reset(proxy_factory()->CreateModemCDMAProxy(
Eric Shienbrood9a245532012-03-07 14:20:39 -050047 cellular()->dbus_path(), cellular()->dbus_owner()));
48 proxy_->set_signal_quality_callback(
49 Bind(&CellularCapabilityCDMA::OnSignalQualitySignal,
50 weak_ptr_factory_.GetWeakPtr()));
51 proxy_->set_activation_state_callback(
52 Bind(&CellularCapabilityCDMA::OnActivationStateChangedSignal,
53 weak_ptr_factory_.GetWeakPtr()));
54 proxy_->set_registration_state_callback(
55 Bind(&CellularCapabilityCDMA::OnRegistrationStateChangedSignal,
56 weak_ptr_factory_.GetWeakPtr()));
Darin Petkovdaf43862011-10-27 11:37:28 +020057}
58
Eric Shienbrood9a245532012-03-07 14:20:39 -050059void CellularCapabilityCDMA::StartModem(Error *error,
60 const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -070061 SLOG(Cellular, 2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -050062 InitProxies();
63
64 CellularTaskList *tasks = new CellularTaskList();
65 ResultCallback cb =
66 Bind(&CellularCapabilityCDMA::StepCompletedCallback,
Thieu Le923006b2012-04-05 16:32:58 -070067 weak_ptr_factory_.GetWeakPtr(), callback, false, tasks);
Eric Shienbrood7fce52c2012-04-13 19:11:02 -040068 if (!cellular()->IsUnderlyingDeviceEnabled())
69 tasks->push_back(Bind(&CellularCapabilityCDMA::EnableModem,
70 weak_ptr_factory_.GetWeakPtr(), cb));
Eric Shienbrood9a245532012-03-07 14:20:39 -050071 tasks->push_back(Bind(&CellularCapabilityCDMA::GetModemStatus,
72 weak_ptr_factory_.GetWeakPtr(), cb));
73 tasks->push_back(Bind(&CellularCapabilityCDMA::GetMEID,
74 weak_ptr_factory_.GetWeakPtr(), cb));
75 tasks->push_back(Bind(&CellularCapabilityCDMA::GetModemInfo,
76 weak_ptr_factory_.GetWeakPtr(), cb));
77 tasks->push_back(Bind(&CellularCapabilityCDMA::FinishEnable,
78 weak_ptr_factory_.GetWeakPtr(), cb));
79
80 RunNextStep(tasks);
81}
82
Eric Shienbrood9a245532012-03-07 14:20:39 -050083void CellularCapabilityCDMA::ReleaseProxies() {
Jason Glasgow82f9ab32012-04-04 14:27:19 -040084 CellularCapabilityClassic::ReleaseProxies();
Darin Petkov721ac932011-11-16 15:43:09 +010085 proxy_.reset();
86}
87
Jason Glasgow82f9ab32012-04-04 14:27:19 -040088bool CellularCapabilityCDMA::AllowRoaming() {
89 return allow_roaming_property();
90}
91
92
Darin Petkov5f316f62011-11-18 12:10:26 +010093void CellularCapabilityCDMA::OnServiceCreated() {
Ben Chanfad4a0b2012-04-18 15:49:59 -070094 SLOG(Cellular, 2) << __func__;
Darin Petkov381928f2012-02-02 23:00:12 +010095 cellular()->service()->SetOLP(olp_);
96 cellular()->service()->SetUsageURL(usage_url_);
Darin Petkov5f316f62011-11-18 12:10:26 +010097 UpdateServingOperator();
98 HandleNewActivationState(MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR);
99}
100
Darin Petkovae0c64e2011-11-15 15:50:27 +0100101void CellularCapabilityCDMA::UpdateStatus(const DBusPropertiesMap &properties) {
102 string carrier;
103 if (DBusProperties::GetString(properties, "carrier", &carrier)) {
104 Cellular::Operator oper;
105 oper.SetName(carrier);
106 oper.SetCountry("us");
107 cellular()->set_home_provider(oper);
108 }
109 DBusProperties::GetUint32(
110 properties, "activation_state", &activation_state_);
111 DBusProperties::GetUint16(properties, "prl_version", &prl_version_);
Darin Petkov5f316f62011-11-18 12:10:26 +0100112 // TODO(petkov): For now, get the payment and usage URLs from ModemManager to
113 // match flimflam. In the future, get these from an alternative source (e.g.,
114 // database, carrier-specific properties, etc.).
Darin Petkov381928f2012-02-02 23:00:12 +0100115 string payment;
116 if (DBusProperties::GetString(properties, "payment_url", &payment)) {
117 olp_.SetURL(payment);
118 }
119 if (DBusProperties::GetString(properties, "payment_url_method", &payment)) {
120 olp_.SetMethod(payment);
121 }
122 if (DBusProperties::GetString(properties, "payment_url_postdata", &payment)) {
123 olp_.SetPostData(payment);
124 }
Darin Petkovae0c64e2011-11-15 15:50:27 +0100125 DBusProperties::GetString(properties, "usage_url", &usage_url_);
126}
127
128void CellularCapabilityCDMA::SetupConnectProperties(
129 DBusPropertiesMap *properties) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500130 (*properties)[kConnectPropertyPhoneNumber].writer().append_string(
Darin Petkovae0c64e2011-11-15 15:50:27 +0100131 kPhoneNumber);
132}
133
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500134void CellularCapabilityCDMA::Activate(const string &carrier,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500135 Error *error,
136 const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700137 SLOG(Cellular, 2) << __func__ << "(" << carrier << ")";
Darin Petkova3d3be52011-11-14 21:34:16 +0100138 if (cellular()->state() != Cellular::kStateEnabled &&
139 cellular()->state() != Cellular::kStateRegistered) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500140 Error::PopulateAndLog(error, Error::kInvalidArguments,
Darin Petkova3d3be52011-11-14 21:34:16 +0100141 "Unable to activate in " +
142 Cellular::GetStateString(cellular()->state()));
143 return;
144 }
Eric Shienbrood9a245532012-03-07 14:20:39 -0500145 ActivationResultCallback cb = Bind(&CellularCapabilityCDMA::OnActivateReply,
146 weak_ptr_factory_.GetWeakPtr(), callback);
147 proxy_->Activate(carrier, error, cb, kTimeoutActivate);
Darin Petkovae0c64e2011-11-15 15:50:27 +0100148}
149
150void CellularCapabilityCDMA::HandleNewActivationState(uint32 error) {
151 if (!cellular()->service().get()) {
152 return;
153 }
Darin Petkovb9c99332012-01-12 13:13:00 +0100154 cellular()->service()->SetActivationState(
Darin Petkovae0c64e2011-11-15 15:50:27 +0100155 GetActivationStateString(activation_state_));
156 cellular()->service()->set_error(GetActivationErrorString(error));
157}
158
159// static
160string CellularCapabilityCDMA::GetActivationStateString(uint32 state) {
161 switch (state) {
162 case MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED:
163 return flimflam::kActivationStateActivated;
164 case MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING:
165 return flimflam::kActivationStateActivating;
166 case MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED:
167 return flimflam::kActivationStateNotActivated;
168 case MM_MODEM_CDMA_ACTIVATION_STATE_PARTIALLY_ACTIVATED:
169 return flimflam::kActivationStatePartiallyActivated;
170 default:
171 return flimflam::kActivationStateUnknown;
172 }
173}
174
175// static
176string CellularCapabilityCDMA::GetActivationErrorString(uint32 error) {
177 switch (error) {
178 case MM_MODEM_CDMA_ACTIVATION_ERROR_WRONG_RADIO_INTERFACE:
179 return flimflam::kErrorNeedEvdo;
180 case MM_MODEM_CDMA_ACTIVATION_ERROR_ROAMING:
181 return flimflam::kErrorNeedHomeNetwork;
182 case MM_MODEM_CDMA_ACTIVATION_ERROR_COULD_NOT_CONNECT:
183 case MM_MODEM_CDMA_ACTIVATION_ERROR_SECURITY_AUTHENTICATION_FAILED:
184 case MM_MODEM_CDMA_ACTIVATION_ERROR_PROVISIONING_FAILED:
185 return flimflam::kErrorOtaspFailed;
186 case MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR:
187 return "";
188 case MM_MODEM_CDMA_ACTIVATION_ERROR_NO_SIGNAL:
189 default:
190 return flimflam::kErrorActivationFailed;
191 }
Darin Petkova3d3be52011-11-14 21:34:16 +0100192}
193
Eric Shienbrood9a245532012-03-07 14:20:39 -0500194void CellularCapabilityCDMA::GetMEID(const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700195 SLOG(Cellular, 2) << __func__;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500196 if (meid_.empty()) {
Darin Petkovcb547732011-11-09 13:55:26 +0100197 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500198 meid_ = proxy_->MEID();
Ben Chanfad4a0b2012-04-18 15:49:59 -0700199 SLOG(Cellular, 2) << "MEID: " << meid_;
Darin Petkovcb547732011-11-09 13:55:26 +0100200 }
Eric Shienbrood9a245532012-03-07 14:20:39 -0500201 callback.Run(Error());
Darin Petkovcb547732011-11-09 13:55:26 +0100202}
203
Eric Shienbrood9a245532012-03-07 14:20:39 -0500204void CellularCapabilityCDMA::GetProperties(const ResultCallback &callback) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700205 SLOG(Cellular, 2) << __func__;
Darin Petkov184c54e2011-11-15 12:44:39 +0100206 // No properties.
Eric Shienbrood9a245532012-03-07 14:20:39 -0500207 callback.Run(Error());
Darin Petkov184c54e2011-11-15 12:44:39 +0100208}
209
Darin Petkovb72cf402011-11-22 14:51:39 +0100210bool CellularCapabilityCDMA::IsRegistered() {
211 return registration_state_evdo_ != MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN ||
212 registration_state_1x_ != MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN;
213}
214
Eric Shienbrood7fce52c2012-04-13 19:11:02 -0400215void CellularCapabilityCDMA::SetUnregistered(bool searching) {
216 registration_state_evdo_ = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN;
217 registration_state_1x_ = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN;
218}
219
Darin Petkov20c13ec2011-11-09 15:07:15 +0100220string CellularCapabilityCDMA::GetNetworkTechnologyString() const {
Darin Petkov184c54e2011-11-15 12:44:39 +0100221 if (registration_state_evdo_ != MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN) {
Darin Petkov20c13ec2011-11-09 15:07:15 +0100222 return flimflam::kNetworkTechnologyEvdo;
223 }
Darin Petkov184c54e2011-11-15 12:44:39 +0100224 if (registration_state_1x_ != MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN) {
Darin Petkov20c13ec2011-11-09 15:07:15 +0100225 return flimflam::kNetworkTechnology1Xrtt;
226 }
227 return "";
228}
229
230string CellularCapabilityCDMA::GetRoamingStateString() const {
Darin Petkov184c54e2011-11-15 12:44:39 +0100231 uint32 state = registration_state_evdo_;
Darin Petkov20c13ec2011-11-09 15:07:15 +0100232 if (state == MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN) {
Darin Petkov184c54e2011-11-15 12:44:39 +0100233 state = registration_state_1x_;
Darin Petkov20c13ec2011-11-09 15:07:15 +0100234 }
235 switch (state) {
236 case MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN:
237 case MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED:
238 break;
239 case MM_MODEM_CDMA_REGISTRATION_STATE_HOME:
240 return flimflam::kRoamingStateHome;
241 case MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING:
242 return flimflam::kRoamingStateRoaming;
243 default:
244 NOTREACHED();
245 }
246 return flimflam::kRoamingStateUnknown;
247}
248
Darin Petkov3e509242011-11-10 14:46:44 +0100249void CellularCapabilityCDMA::GetSignalQuality() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700250 SLOG(Cellular, 2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500251 SignalQualityCallback callback =
252 Bind(&CellularCapabilityCDMA::OnGetSignalQualityReply,
253 weak_ptr_factory_.GetWeakPtr());
254 proxy_->GetSignalQuality(NULL, callback, kTimeoutDefault);
Darin Petkov184c54e2011-11-15 12:44:39 +0100255}
256
Eric Shienbrood9a245532012-03-07 14:20:39 -0500257void CellularCapabilityCDMA::GetRegistrationState() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700258 SLOG(Cellular, 2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500259 RegistrationStateCallback callback =
260 Bind(&CellularCapabilityCDMA::OnGetRegistrationStateReply,
261 weak_ptr_factory_.GetWeakPtr());
262 proxy_->GetRegistrationState(NULL, callback, kTimeoutDefault);
Darin Petkov184c54e2011-11-15 12:44:39 +0100263}
264
Darin Petkovac635a82012-01-10 16:51:58 +0100265string CellularCapabilityCDMA::CreateFriendlyServiceName() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700266 SLOG(Cellular, 2) << __func__;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500267 if (!carrier_.empty()) {
268 return carrier_;
Darin Petkovac635a82012-01-10 16:51:58 +0100269 }
270 return base::StringPrintf("CDMANetwork%u", friendly_service_name_id_++);
271}
272
Darin Petkovae0c64e2011-11-15 15:50:27 +0100273void CellularCapabilityCDMA::UpdateServingOperator() {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700274 SLOG(Cellular, 2) << __func__;
Darin Petkovae0c64e2011-11-15 15:50:27 +0100275 if (cellular()->service().get()) {
Darin Petkov9cb02682012-01-28 00:17:38 +0100276 cellular()->service()->SetServingOperator(cellular()->home_provider());
Darin Petkovae0c64e2011-11-15 15:50:27 +0100277 }
278}
279
Eric Shienbrood9a245532012-03-07 14:20:39 -0500280void CellularCapabilityCDMA::OnActivateReply(
281 const ResultCallback &callback, uint32 status, const Error &error) {
282 if (error.IsSuccess()) {
283 if (status == MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR) {
284 activation_state_ = MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING;
285 }
286 HandleNewActivationState(status);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500287 }
Eric Shienbrood9a245532012-03-07 14:20:39 -0500288 callback.Run(error);
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500289}
290
Eric Shienbrood9a245532012-03-07 14:20:39 -0500291void CellularCapabilityCDMA::OnGetRegistrationStateReply(
292 uint32 state_1x, uint32 state_evdo, const Error &error) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700293 SLOG(Cellular, 2) << __func__;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500294 if (error.IsSuccess())
295 OnRegistrationStateChangedSignal(state_1x, state_evdo);
296}
297
298void CellularCapabilityCDMA::OnGetSignalQualityReply(uint32 quality,
299 const Error &error) {
300 if (error.IsSuccess())
301 OnSignalQualitySignal(quality);
302}
303
304void CellularCapabilityCDMA::OnActivationStateChangedSignal(
Darin Petkov184c54e2011-11-15 12:44:39 +0100305 uint32 activation_state,
306 uint32 activation_error,
307 const DBusPropertiesMap &status_changes) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700308 SLOG(Cellular, 2) << __func__;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500309 DBusProperties::GetString(status_changes, "mdn", &mdn_);
310 DBusProperties::GetString(status_changes, "min", &min_);
Darin Petkov381928f2012-02-02 23:00:12 +0100311 string payment;
312 if (DBusProperties::GetString(status_changes, "payment_url", &payment)) {
313 olp_.SetURL(payment);
314 }
315 if (DBusProperties::GetString(
316 status_changes, "payment_url_method", &payment)) {
317 olp_.SetMethod(payment);
318 }
319 if (DBusProperties::GetString(
320 status_changes, "payment_url_postdata", &payment)) {
321 olp_.SetPostData(payment);
322 }
323 if (cellular()->service().get()) {
324 cellular()->service()->SetOLP(olp_);
Darin Petkov184c54e2011-11-15 12:44:39 +0100325 }
Darin Petkovae0c64e2011-11-15 15:50:27 +0100326 activation_state_ = activation_state;
327 HandleNewActivationState(activation_error);
Darin Petkov184c54e2011-11-15 12:44:39 +0100328}
329
Eric Shienbrood9a245532012-03-07 14:20:39 -0500330void CellularCapabilityCDMA::OnRegistrationStateChangedSignal(
Darin Petkov184c54e2011-11-15 12:44:39 +0100331 uint32 state_1x, uint32 state_evdo) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700332 SLOG(Cellular, 2) << __func__;
Darin Petkov184c54e2011-11-15 12:44:39 +0100333 registration_state_1x_ = state_1x;
334 registration_state_evdo_ = state_evdo;
335 cellular()->HandleNewRegistrationState();
336}
337
Eric Shienbrood9a245532012-03-07 14:20:39 -0500338void CellularCapabilityCDMA::OnSignalQualitySignal(uint32 strength) {
Darin Petkov3e509242011-11-10 14:46:44 +0100339 cellular()->HandleNewSignalQuality(strength);
340}
341
Darin Petkovdaf43862011-10-27 11:37:28 +0200342} // namespace shill