blob: 5a26d7520f7d2771d662a75b54ff944f7781636e [file] [log] [blame]
Chris Masone3bd3c8c2011-06-13 08:20:26 -07001// Copyright (c) 2011 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.h"
6
7#include <string>
Chris Masone889666b2011-07-03 12:58:50 -07008#include <utility>
9#include <vector>
Chris Masone3bd3c8c2011-06-13 08:20:26 -070010
11#include <base/logging.h>
Darin Petkove9d12e02011-07-27 15:09:37 -070012#include <base/stringprintf.h>
Chris Masoneb925cc82011-06-22 15:39:57 -070013#include <chromeos/dbus/service_constants.h>
Darin Petkovbec79a22011-08-01 14:47:17 -070014#include <mm/mm-modem.h>
Chris Masone3bd3c8c2011-06-13 08:20:26 -070015
16#include "shill/cellular_service.h"
17#include "shill/control_interface.h"
18#include "shill/device.h"
19#include "shill/device_info.h"
20#include "shill/manager.h"
Darin Petkovbec79a22011-08-01 14:47:17 -070021#include "shill/modem_cdma_proxy_interface.h"
Darin Petkove9d12e02011-07-27 15:09:37 -070022#include "shill/modem_proxy_interface.h"
Darin Petkove604f702011-07-28 15:51:17 -070023#include "shill/modem_simple_proxy_interface.h"
Chris Masone7aa5f902011-07-11 11:13:35 -070024#include "shill/profile.h"
Chris Masone889666b2011-07-03 12:58:50 -070025#include "shill/property_accessor.h"
Darin Petkove9d12e02011-07-27 15:09:37 -070026#include "shill/proxy_factory.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070027#include "shill/shill_event.h"
28
Chris Masone889666b2011-07-03 12:58:50 -070029using std::make_pair;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070030using std::string;
Chris Masone889666b2011-07-03 12:58:50 -070031using std::vector;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070032
33namespace shill {
34
Chris Masone889666b2011-07-03 12:58:50 -070035Cellular::Network::Network() {
36 dict_[flimflam::kStatusProperty] = "";
37 dict_[flimflam::kNetworkIdProperty] = "";
38 dict_[flimflam::kShortNameProperty] = "";
39 dict_[flimflam::kLongNameProperty] = "";
40 dict_[flimflam::kTechnologyProperty] = "";
41}
42
43Cellular::Network::~Network() {}
44
45const std::string &Cellular::Network::GetStatus() const {
46 return dict_.find(flimflam::kStatusProperty)->second;
47}
48
49void Cellular::Network::SetStatus(const std::string &status) {
50 dict_[flimflam::kStatusProperty] = status;
51}
52
53const std::string &Cellular::Network::GetId() const {
54 return dict_.find(flimflam::kNetworkIdProperty)->second;
55}
56
57void Cellular::Network::SetId(const std::string &id) {
58 dict_[flimflam::kNetworkIdProperty] = id;
59}
60
61const std::string &Cellular::Network::GetShortName() const {
62 return dict_.find(flimflam::kShortNameProperty)->second;
63}
64
65void Cellular::Network::SetShortName(const std::string &name) {
66 dict_[flimflam::kShortNameProperty] = name;
67}
68
69const std::string &Cellular::Network::GetLongName() const {
70 return dict_.find(flimflam::kLongNameProperty)->second;
71}
72
73void Cellular::Network::SetLongName(const std::string &name) {
74 dict_[flimflam::kLongNameProperty] = name;
75}
76
77const std::string &Cellular::Network::GetTechnology() const {
78 return dict_.find(flimflam::kTechnologyProperty)->second;
79}
80
81void Cellular::Network::SetTechnology(const std::string &technology) {
82 dict_[flimflam::kTechnologyProperty] = technology;
83}
84
85const Stringmap &Cellular::Network::ToDict() const {
86 return dict_;
87}
88
Darin Petkovbec79a22011-08-01 14:47:17 -070089Cellular::CDMA::CDMA()
90 : registration_state_evdo(MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN),
91 registration_state_1x(MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN),
92 activation_state(MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED) {}
93
Chris Masone3bd3c8c2011-06-13 08:20:26 -070094Cellular::Cellular(ControlInterface *control_interface,
95 EventDispatcher *dispatcher,
96 Manager *manager,
Darin Petkove9d12e02011-07-27 15:09:37 -070097 const string &link_name,
98 int interface_index,
99 Type type,
100 const string &owner,
101 const string &path)
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700102 : Device(control_interface,
103 dispatcher,
104 manager,
Darin Petkove9d12e02011-07-27 15:09:37 -0700105 link_name,
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700106 interface_index),
Darin Petkove9d12e02011-07-27 15:09:37 -0700107 type_(type),
108 state_(kStateDisabled),
109 dbus_owner_(owner),
110 dbus_path_(path),
Darin Petkove9d12e02011-07-27 15:09:37 -0700111 service_registered_(false),
112 allow_roaming_(false),
113 prl_version_(0),
114 scanning_(false),
115 scan_interval_(0) {
116 store_.RegisterConstString(flimflam::kDBusConnectionProperty, &dbus_owner_);
117 store_.RegisterConstString(flimflam::kDBusObjectProperty, &dbus_path_);
Chris Masone27c4aa52011-07-02 13:10:14 -0700118 store_.RegisterConstString(flimflam::kCarrierProperty, &carrier_);
Chris Masone4d42df82011-07-02 17:09:39 -0700119 store_.RegisterBool(flimflam::kCellularAllowRoamingProperty, &allow_roaming_);
Chris Masone27c4aa52011-07-02 13:10:14 -0700120 store_.RegisterConstString(flimflam::kEsnProperty, &esn_);
Chris Masone27c4aa52011-07-02 13:10:14 -0700121 store_.RegisterConstString(flimflam::kFirmwareRevisionProperty,
122 &firmware_revision_);
123 store_.RegisterConstString(flimflam::kHardwareRevisionProperty,
124 &hardware_revision_);
Chris Masone4d42df82011-07-02 17:09:39 -0700125 store_.RegisterConstString(flimflam::kImeiProperty, &imei_);
126 store_.RegisterConstString(flimflam::kImsiProperty, &imsi_);
127 store_.RegisterConstString(flimflam::kManufacturerProperty, &manufacturer_);
128 store_.RegisterConstString(flimflam::kMdnProperty, &mdn_);
129 store_.RegisterConstString(flimflam::kMeidProperty, &meid_);
130 store_.RegisterConstString(flimflam::kMinProperty, &min_);
131 store_.RegisterConstString(flimflam::kModelIDProperty, &model_id_);
Darin Petkovceb68172011-07-29 14:47:48 -0700132 store_.RegisterConstUint16(flimflam::kPRLVersionProperty, &prl_version_);
Chris Masoneb925cc82011-06-22 15:39:57 -0700133
Chris Masone889666b2011-07-03 12:58:50 -0700134 HelpRegisterDerivedStrIntPair(flimflam::kSIMLockStatusProperty,
135 &Cellular::SimLockStatusToProperty,
136 NULL);
137 HelpRegisterDerivedStringmaps(flimflam::kFoundNetworksProperty,
138 &Cellular::EnumerateNetworks,
139 NULL);
Chris Masoneb925cc82011-06-22 15:39:57 -0700140
Chris Masone4d42df82011-07-02 17:09:39 -0700141 store_.RegisterConstBool(flimflam::kScanningProperty, &scanning_);
142 store_.RegisterUint16(flimflam::kScanIntervalProperty, &scan_interval_);
143
Darin Petkove9d12e02011-07-27 15:09:37 -0700144 VLOG(2) << "Cellular device " << link_name_ << " initialized: "
145 << GetTypeString();
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700146}
147
Darin Petkove9d12e02011-07-27 15:09:37 -0700148Cellular::~Cellular() {}
149
150std::string Cellular::GetTypeString() {
151 switch (type_) {
152 case kTypeGSM: return "CellularTypeGSM";
153 case kTypeCDMA: return "CellularTypeCDMA";
154 default: return StringPrintf("CellularTypeUnknown-%d", type_);
155 }
156}
157
158std::string Cellular::GetStateString() {
159 switch (state_) {
160 case kStateDisabled: return "CellularStateDisabled";
161 case kStateEnabled: return "CellularStateEnabled";
162 case kStateRegistered: return "CellularStateRegistered";
163 case kStateConnected: return "CellularStateConnected";
164 default: return StringPrintf("CellularStateUnknown-%d", state_);
165 }
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700166}
167
168void Cellular::Start() {
Darin Petkovf5f61e02011-07-29 11:35:40 -0700169 VLOG(2) << __func__ << ": " << GetStateString();
Darin Petkovbec79a22011-08-01 14:47:17 -0700170 InitProxies();
Darin Petkovf5f61e02011-07-29 11:35:40 -0700171 EnableModem();
Darin Petkovceb68172011-07-29 14:47:48 -0700172 if (type_ == kTypeGSM) {
173 RegisterGSMModem();
174 }
Darin Petkovf5f61e02011-07-29 11:35:40 -0700175 GetModemStatus();
Darin Petkovceb68172011-07-29 14:47:48 -0700176 GetModemIdentifiers();
177 if (type_ == kTypeGSM) {
178 GetGSMProperties();
179 }
180 GetModemInfo();
181 GetModemRegistrationState();
Darin Petkove9d12e02011-07-27 15:09:37 -0700182 // TODO(petkov): Device::Start();
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700183}
184
185void Cellular::Stop() {
Darin Petkove9d12e02011-07-27 15:09:37 -0700186 proxy_.reset();
Darin Petkove604f702011-07-28 15:51:17 -0700187 simple_proxy_.reset();
Darin Petkovbec79a22011-08-01 14:47:17 -0700188 cdma_proxy_.reset();
Chris Masone2b105542011-06-22 10:58:09 -0700189 manager_->DeregisterService(service_);
Darin Petkove9d12e02011-07-27 15:09:37 -0700190 service_ = NULL; // Breaks a reference cycle.
Darin Petkovd9661952011-08-03 16:25:42 -0700191 state_ = kStateDisabled;
Darin Petkove9d12e02011-07-27 15:09:37 -0700192 // TODO(petkov): Device::Stop();
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700193}
194
Darin Petkovbec79a22011-08-01 14:47:17 -0700195void Cellular::InitProxies() {
196 proxy_.reset(
197 ProxyFactory::factory()->CreateModemProxy(dbus_path_, dbus_owner_));
198 simple_proxy_.reset(
199 ProxyFactory::factory()->CreateModemSimpleProxy(
200 dbus_path_, dbus_owner_));
201 switch (type_) {
202 case kTypeGSM:
203 NOTIMPLEMENTED();
204 break;
205 case kTypeCDMA:
206 cdma_proxy_.reset(
207 ProxyFactory::factory()->CreateModemCDMAProxy(
Darin Petkovd9661952011-08-03 16:25:42 -0700208 this, dbus_path_, dbus_owner_));
Darin Petkovbec79a22011-08-01 14:47:17 -0700209 break;
210 default: NOTREACHED();
211 }
212}
213
Darin Petkovf5f61e02011-07-29 11:35:40 -0700214void Cellular::EnableModem() {
215 CHECK_EQ(kStateDisabled, state_);
216 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
217 proxy_->Enable(true);
218 state_ = kStateEnabled;
219}
220
221void Cellular::GetModemStatus() {
Darin Petkovceb68172011-07-29 14:47:48 -0700222 CHECK_EQ(kStateEnabled, state_);
Darin Petkovf5f61e02011-07-29 11:35:40 -0700223 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
224 DBusPropertiesMap properties = simple_proxy_->GetStatus();
Darin Petkovceb68172011-07-29 14:47:48 -0700225 if (DBusProperties::GetString(properties, "carrier", &carrier_) &&
226 type_ == kTypeCDMA) {
227 // TODO(petkov): Set Cellular.FirmwareImageName and home_provider based on
228 // the carrier.
Darin Petkovf5f61e02011-07-29 11:35:40 -0700229 }
Darin Petkovceb68172011-07-29 14:47:48 -0700230 DBusProperties::GetString(properties, "meid", &meid_);
231 DBusProperties::GetString(properties, "imei", &imei_);
232 if (DBusProperties::GetString(properties, "imsi", &imsi_) &&
233 type_ == kTypeGSM) {
234 // TODO(petkov): Set GSM provider.
235 }
236 DBusProperties::GetString(properties, "esn", &esn_);
237 DBusProperties::GetString(properties, "mdn", &mdn_);
238 DBusProperties::GetString(properties, "min", &min_);
239 DBusProperties::GetUint16(properties, "prl_version", &prl_version_);
240 DBusProperties::GetString(
241 properties, "firmware_revision", &firmware_revision_);
242 // TODO(petkov): Get payment_url/olp_url/usage_url. For now, get these from
243 // ModemManager to match flimflam. In the future, provide a plugin API to get
244 // these directly from the modem driver.
245 if (type_ == kTypeCDMA) {
246 // TODO(petkov): Get activation_state.
247 }
248}
249
250void Cellular::GetModemIdentifiers() {
251 // TODO(petkov): Implement this.
252 NOTIMPLEMENTED();
253}
254
255void Cellular::GetGSMProperties() {
256 // TODO(petkov): Implement this.
257 NOTIMPLEMENTED();
258}
259
260void Cellular::RegisterGSMModem() {
261 // TODO(petkov): Invoke ModemManager.Modem.Gsm.Network.Register.
262 NOTIMPLEMENTED();
263}
264
265void Cellular::GetModemInfo() {
266 ModemProxyInterface::Info info = proxy_->GetInfo();
267 manufacturer_ = info._1;
268 model_id_ = info._2;
269 hardware_revision_ = info._3;
270 VLOG(2) << "ModemInfo: " << manufacturer_ << ", " << model_id_ << ", "
271 << hardware_revision_;
272}
273
274void Cellular::GetModemRegistrationState() {
Darin Petkovbec79a22011-08-01 14:47:17 -0700275 switch (type_) {
276 case kTypeGSM:
277 GetGSMRegistrationState();
278 break;
279 case kTypeCDMA:
280 GetCDMARegistrationState();
281 break;
282 default: NOTREACHED();
283 }
Darin Petkovd9661952011-08-03 16:25:42 -0700284 HandleNewRegistrationState();
Darin Petkovbec79a22011-08-01 14:47:17 -0700285}
286
287void Cellular::GetCDMARegistrationState() {
288 CHECK_EQ(kTypeCDMA, type_);
289 cdma_proxy_->GetRegistrationState(&cdma_.registration_state_1x,
290 &cdma_.registration_state_evdo);
291 VLOG(2) << "CDMA Registration: 1x(" << cdma_.registration_state_1x
292 << ") EVDO(" << cdma_.registration_state_evdo << ")";
293 // TODO(petkov): handle_reported_connect?
294}
295
296void Cellular::GetGSMRegistrationState() {
Darin Petkovceb68172011-07-29 14:47:48 -0700297 // TODO(petkov): Implement this.
298 NOTIMPLEMENTED();
299}
300
Darin Petkovd9661952011-08-03 16:25:42 -0700301bool Cellular::IsModemRegistered() {
302 return cdma_.registration_state_1x !=
303 MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN ||
304 cdma_.registration_state_evdo !=
305 MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN;
306 // TODO(petkov): Handle GSM states.
307}
308
309void Cellular::HandleNewRegistrationState() {
310 VLOG(2) << __func__;
311 if (!IsModemRegistered()) {
312 service_ = NULL;
313 if (state_ == kStateConnected || state_ == kStateRegistered) {
314 state_ = kStateEnabled;
315 }
316 return;
317 }
318
319 if (state_ == kStateEnabled) {
320 state_ = kStateRegistered;
321 }
322 if (!service_.get()) {
323 // For now, no endpoint is created. Revisit if necessary.
324 CreateService();
325 }
326 GetModemSignalQuality();
327 // TODO(petkov): Update the service.
328}
329
330void Cellular::GetModemSignalQuality() {
331 uint32 strength = 0;
332 switch (type_) {
333 case kTypeGSM:
334 strength = GetGSMSignalQuality();
335 break;
336 case kTypeCDMA:
337 strength = GetCDMASignalQuality();
338 break;
339 default: NOTREACHED();
340 }
341 HandleNewSignalQuality(strength);
342}
343
344uint32 Cellular::GetCDMASignalQuality() {
345 CHECK_EQ(kTypeCDMA, type_);
346 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
347 return cdma_proxy_->GetSignalQuality();
348}
349
350uint32 Cellular::GetGSMSignalQuality() {
Darin Petkovceb68172011-07-29 14:47:48 -0700351 // TODO(petkov): Implement this.
352 NOTIMPLEMENTED();
Darin Petkovd9661952011-08-03 16:25:42 -0700353 return 0;
354}
355
356void Cellular::HandleNewSignalQuality(uint32 strength) {
357 VLOG(2) << "Signal strength: " << strength;
358 if (service_.get()) {
359 service_->set_strength(strength);
360 }
361}
362
363void Cellular::CreateService() {
364 CHECK(!service_.get());
365 service_ =
366 new CellularService(control_interface_, dispatcher_, manager_, this);
367 // TODO(petkov): Set activation_state.
368 // TODO(petkov): Set operator.
369 // TODO(petkov): Set old_url/usage_url.
Darin Petkovf5f61e02011-07-29 11:35:40 -0700370}
371
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700372bool Cellular::TechnologyIs(const Device::Technology type) {
373 return type == Device::kCellular;
374}
375
Darin Petkovd9661952011-08-03 16:25:42 -0700376void Cellular::OnCDMARegistrationStateChanged(uint32 state_1x,
377 uint32 state_evdo) {
378 CHECK_EQ(kTypeCDMA, type_);
379 cdma_.registration_state_1x = state_1x;
380 cdma_.registration_state_evdo = state_evdo;
381 HandleNewRegistrationState();
382}
383
384void Cellular::OnCDMASignalQualityChanged(uint32 strength) {
385 CHECK_EQ(kTypeCDMA, type_);
386 HandleNewSignalQuality(strength);
387}
388
Chris Masone889666b2011-07-03 12:58:50 -0700389Stringmaps Cellular::EnumerateNetworks() {
390 Stringmaps to_return;
391 for (vector<Network>::const_iterator it = found_networks_.begin();
392 it != found_networks_.end();
393 ++it) {
394 to_return.push_back(it->ToDict());
395 }
396 return to_return;
397}
398
399StrIntPair Cellular::SimLockStatusToProperty() {
400 return StrIntPair(make_pair(flimflam::kSIMLockTypeProperty,
401 sim_lock_status_.lock_type),
402 make_pair(flimflam::kSIMLockRetriesLeftProperty,
403 sim_lock_status_.retries_left));
404}
405
406void Cellular::HelpRegisterDerivedStringmaps(
407 const string &name,
408 Stringmaps(Cellular::*get)(void),
409 bool(Cellular::*set)(const Stringmaps&)) {
410 store_.RegisterDerivedStringmaps(
411 name,
412 StringmapsAccessor(
413 new CustomAccessor<Cellular, Stringmaps>(this, get, set)));
414}
415
416void Cellular::HelpRegisterDerivedStrIntPair(
417 const string &name,
418 StrIntPair(Cellular::*get)(void),
419 bool(Cellular::*set)(const StrIntPair&)) {
420 store_.RegisterDerivedStrIntPair(
421 name,
422 StrIntPairAccessor(
423 new CustomAccessor<Cellular, StrIntPair>(this, get, set)));
424}
425
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700426} // namespace shill