blob: 8d357eb313847b665202a753254ed026bb016155 [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
Darin Petkov0828f5f2011-08-11 10:18:52 -07007#include <netinet/in.h>
8#include <linux/if.h>
9
Chris Masone3bd3c8c2011-06-13 08:20:26 -070010#include <string>
Chris Masone889666b2011-07-03 12:58:50 -070011#include <utility>
12#include <vector>
Chris Masone3bd3c8c2011-06-13 08:20:26 -070013
14#include <base/logging.h>
Darin Petkove9d12e02011-07-27 15:09:37 -070015#include <base/stringprintf.h>
Chris Masoneb925cc82011-06-22 15:39:57 -070016#include <chromeos/dbus/service_constants.h>
Darin Petkovbec79a22011-08-01 14:47:17 -070017#include <mm/mm-modem.h>
Chris Masone3bd3c8c2011-06-13 08:20:26 -070018
19#include "shill/cellular_service.h"
20#include "shill/control_interface.h"
21#include "shill/device.h"
22#include "shill/device_info.h"
Darin Petkov4d6d9412011-08-24 13:19:54 -070023#include "shill/error.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070024#include "shill/manager.h"
Darin Petkove604f702011-07-28 15:51:17 -070025#include "shill/modem_simple_proxy_interface.h"
Chris Masone7aa5f902011-07-11 11:13:35 -070026#include "shill/profile.h"
Chris Masone889666b2011-07-03 12:58:50 -070027#include "shill/property_accessor.h"
Darin Petkove9d12e02011-07-27 15:09:37 -070028#include "shill/proxy_factory.h"
Darin Petkov0828f5f2011-08-11 10:18:52 -070029#include "shill/rtnl_handler.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070030#include "shill/shill_event.h"
31
Chris Masone889666b2011-07-03 12:58:50 -070032using std::make_pair;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070033using std::string;
Chris Masone889666b2011-07-03 12:58:50 -070034using std::vector;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070035
36namespace shill {
37
Darin Petkovc5f56562011-08-06 16:40:05 -070038const char Cellular::kConnectPropertyPhoneNumber[] = "number";
39const char Cellular::kPhoneNumberCDMA[] = "#777";
40const char Cellular::kPhoneNumberGSM[] = "*99#";
41
Darin Petkov3335b372011-08-22 11:05:32 -070042Cellular::Operator::Operator() {
43 SetName("");
44 SetCode("");
45 SetCountry("");
46}
47
48Cellular::Operator::~Operator() {}
49
50void Cellular::Operator::CopyFrom(const Operator &oper) {
51 dict_ = oper.dict_;
52}
53
54const string &Cellular::Operator::GetName() const {
55 return dict_.find(flimflam::kOperatorNameKey)->second;
56}
57
58void Cellular::Operator::SetName(const string &name) {
59 dict_[flimflam::kOperatorNameKey] = name;
60}
61
62const string &Cellular::Operator::GetCode() const {
63 return dict_.find(flimflam::kOperatorCodeKey)->second;
64}
65
66void Cellular::Operator::SetCode(const string &code) {
67 dict_[flimflam::kOperatorCodeKey] = code;
68}
69
70const string &Cellular::Operator::GetCountry() const {
71 return dict_.find(flimflam::kOperatorCountryKey)->second;
72}
73
74void Cellular::Operator::SetCountry(const string &country) {
75 dict_[flimflam::kOperatorCountryKey] = country;
76}
77
78const Stringmap &Cellular::Operator::ToDict() const {
79 return dict_;
80}
81
Chris Masone889666b2011-07-03 12:58:50 -070082Cellular::Network::Network() {
83 dict_[flimflam::kStatusProperty] = "";
84 dict_[flimflam::kNetworkIdProperty] = "";
85 dict_[flimflam::kShortNameProperty] = "";
86 dict_[flimflam::kLongNameProperty] = "";
87 dict_[flimflam::kTechnologyProperty] = "";
88}
89
90Cellular::Network::~Network() {}
91
Darin Petkov3335b372011-08-22 11:05:32 -070092const string &Cellular::Network::GetStatus() const {
Chris Masone889666b2011-07-03 12:58:50 -070093 return dict_.find(flimflam::kStatusProperty)->second;
94}
95
Darin Petkov3335b372011-08-22 11:05:32 -070096void Cellular::Network::SetStatus(const string &status) {
Chris Masone889666b2011-07-03 12:58:50 -070097 dict_[flimflam::kStatusProperty] = status;
98}
99
Darin Petkov3335b372011-08-22 11:05:32 -0700100const string &Cellular::Network::GetId() const {
Chris Masone889666b2011-07-03 12:58:50 -0700101 return dict_.find(flimflam::kNetworkIdProperty)->second;
102}
103
Darin Petkov3335b372011-08-22 11:05:32 -0700104void Cellular::Network::SetId(const string &id) {
Chris Masone889666b2011-07-03 12:58:50 -0700105 dict_[flimflam::kNetworkIdProperty] = id;
106}
107
Darin Petkov3335b372011-08-22 11:05:32 -0700108const string &Cellular::Network::GetShortName() const {
Chris Masone889666b2011-07-03 12:58:50 -0700109 return dict_.find(flimflam::kShortNameProperty)->second;
110}
111
Darin Petkov3335b372011-08-22 11:05:32 -0700112void Cellular::Network::SetShortName(const string &name) {
Chris Masone889666b2011-07-03 12:58:50 -0700113 dict_[flimflam::kShortNameProperty] = name;
114}
115
Darin Petkov3335b372011-08-22 11:05:32 -0700116const string &Cellular::Network::GetLongName() const {
Chris Masone889666b2011-07-03 12:58:50 -0700117 return dict_.find(flimflam::kLongNameProperty)->second;
118}
119
Darin Petkov3335b372011-08-22 11:05:32 -0700120void Cellular::Network::SetLongName(const string &name) {
Chris Masone889666b2011-07-03 12:58:50 -0700121 dict_[flimflam::kLongNameProperty] = name;
122}
123
Darin Petkov3335b372011-08-22 11:05:32 -0700124const string &Cellular::Network::GetTechnology() const {
Chris Masone889666b2011-07-03 12:58:50 -0700125 return dict_.find(flimflam::kTechnologyProperty)->second;
126}
127
Darin Petkov3335b372011-08-22 11:05:32 -0700128void Cellular::Network::SetTechnology(const string &technology) {
Chris Masone889666b2011-07-03 12:58:50 -0700129 dict_[flimflam::kTechnologyProperty] = technology;
130}
131
132const Stringmap &Cellular::Network::ToDict() const {
133 return dict_;
134}
135
Darin Petkovbec79a22011-08-01 14:47:17 -0700136Cellular::CDMA::CDMA()
137 : registration_state_evdo(MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN),
138 registration_state_1x(MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN),
Darin Petkovcc044422011-08-17 13:30:06 -0700139 activation_state(MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED),
140 prl_version(0) {}
Darin Petkovbec79a22011-08-01 14:47:17 -0700141
Darin Petkov9bac6fe2011-08-26 12:49:05 -0700142Cellular::GSM::GSM()
143 : registration_state(MM_MODEM_GSM_NETWORK_REG_STATUS_UNKNOWN),
144 access_technology(MM_MODEM_GSM_ACCESS_TECH_UNKNOWN) {}
145
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700146Cellular::Cellular(ControlInterface *control_interface,
147 EventDispatcher *dispatcher,
148 Manager *manager,
Darin Petkove9d12e02011-07-27 15:09:37 -0700149 const string &link_name,
Darin Petkov3335b372011-08-22 11:05:32 -0700150 const string &address,
Darin Petkove9d12e02011-07-27 15:09:37 -0700151 int interface_index,
152 Type type,
153 const string &owner,
154 const string &path)
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700155 : Device(control_interface,
156 dispatcher,
157 manager,
Darin Petkove9d12e02011-07-27 15:09:37 -0700158 link_name,
Chris Masone626719f2011-08-18 16:58:48 -0700159 address,
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700160 interface_index),
Darin Petkove9d12e02011-07-27 15:09:37 -0700161 type_(type),
162 state_(kStateDisabled),
Darin Petkovbac96002011-08-09 13:22:00 -0700163 modem_state_(kModemStateUnknown),
Darin Petkove9d12e02011-07-27 15:09:37 -0700164 dbus_owner_(owner),
165 dbus_path_(path),
Darin Petkovc5f56562011-08-06 16:40:05 -0700166 task_factory_(this),
Darin Petkove9d12e02011-07-27 15:09:37 -0700167 allow_roaming_(false),
Darin Petkove9d12e02011-07-27 15:09:37 -0700168 scanning_(false),
169 scan_interval_(0) {
Paul Stewartac4ac002011-08-26 12:04:26 -0700170 PropertyStore *store = this->store();
171 store->RegisterConstString(flimflam::kCarrierProperty, &carrier_);
172 store->RegisterConstString(flimflam::kDBusConnectionProperty, &dbus_owner_);
173 store->RegisterConstString(flimflam::kDBusObjectProperty, &dbus_path_);
174 store->RegisterBool(flimflam::kCellularAllowRoamingProperty, &allow_roaming_);
175 store->RegisterConstString(flimflam::kEsnProperty, &esn_);
176 store->RegisterConstString(flimflam::kFirmwareRevisionProperty,
Chris Masone27c4aa52011-07-02 13:10:14 -0700177 &firmware_revision_);
Paul Stewartac4ac002011-08-26 12:04:26 -0700178 store->RegisterConstString(flimflam::kHardwareRevisionProperty,
Chris Masone27c4aa52011-07-02 13:10:14 -0700179 &hardware_revision_);
Paul Stewartac4ac002011-08-26 12:04:26 -0700180 store->RegisterConstStringmap(flimflam::kHomeProviderProperty,
Darin Petkov3335b372011-08-22 11:05:32 -0700181 &home_provider_.ToDict());
Paul Stewartac4ac002011-08-26 12:04:26 -0700182 store->RegisterConstString(flimflam::kImeiProperty, &imei_);
183 store->RegisterConstString(flimflam::kImsiProperty, &imsi_);
184 store->RegisterConstString(flimflam::kManufacturerProperty, &manufacturer_);
185 store->RegisterConstString(flimflam::kMdnProperty, &mdn_);
186 store->RegisterConstString(flimflam::kMeidProperty, &meid_);
187 store->RegisterConstString(flimflam::kMinProperty, &min_);
188 store->RegisterConstString(flimflam::kModelIDProperty, &model_id_);
189 store->RegisterConstUint16(flimflam::kPRLVersionProperty, &cdma_.prl_version);
190 store->RegisterConstString(flimflam::kSelectedNetworkProperty,
Darin Petkova1e0a1c2011-08-25 15:08:33 -0700191 &selected_network_);
Chris Masoneb925cc82011-06-22 15:39:57 -0700192
Chris Masone889666b2011-07-03 12:58:50 -0700193 HelpRegisterDerivedStrIntPair(flimflam::kSIMLockStatusProperty,
194 &Cellular::SimLockStatusToProperty,
195 NULL);
196 HelpRegisterDerivedStringmaps(flimflam::kFoundNetworksProperty,
197 &Cellular::EnumerateNetworks,
198 NULL);
Chris Masoneb925cc82011-06-22 15:39:57 -0700199
Paul Stewartac4ac002011-08-26 12:04:26 -0700200 store->RegisterConstBool(flimflam::kScanningProperty, &scanning_);
201 store->RegisterUint16(flimflam::kScanIntervalProperty, &scan_interval_);
Chris Masone4d42df82011-07-02 17:09:39 -0700202
Paul Stewartac4ac002011-08-26 12:04:26 -0700203 VLOG(2) << "Cellular device " << this->link_name() << " initialized: "
Darin Petkove9d12e02011-07-27 15:09:37 -0700204 << GetTypeString();
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700205}
206
Darin Petkove9d12e02011-07-27 15:09:37 -0700207Cellular::~Cellular() {}
208
Darin Petkovcc044422011-08-17 13:30:06 -0700209string Cellular::GetTypeString() const {
Darin Petkove9d12e02011-07-27 15:09:37 -0700210 switch (type_) {
211 case kTypeGSM: return "CellularTypeGSM";
212 case kTypeCDMA: return "CellularTypeCDMA";
Darin Petkov0828f5f2011-08-11 10:18:52 -0700213 default: NOTREACHED();
Darin Petkove9d12e02011-07-27 15:09:37 -0700214 }
Darin Petkov0828f5f2011-08-11 10:18:52 -0700215 return StringPrintf("CellularTypeUnknown-%d", type_);
Darin Petkove9d12e02011-07-27 15:09:37 -0700216}
217
Darin Petkovcc044422011-08-17 13:30:06 -0700218// static
219string Cellular::GetStateString(State state) {
220 switch (state) {
Darin Petkove9d12e02011-07-27 15:09:37 -0700221 case kStateDisabled: return "CellularStateDisabled";
222 case kStateEnabled: return "CellularStateEnabled";
223 case kStateRegistered: return "CellularStateRegistered";
224 case kStateConnected: return "CellularStateConnected";
Darin Petkov0828f5f2011-08-11 10:18:52 -0700225 case kStateLinked: return "CellularStateLinked";
226 default: NOTREACHED();
Darin Petkove9d12e02011-07-27 15:09:37 -0700227 }
Darin Petkovcc044422011-08-17 13:30:06 -0700228 return StringPrintf("CellularStateUnknown-%d", state);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700229}
230
Darin Petkovd2045802011-08-23 11:09:25 -0700231string Cellular::GetNetworkTechnologyString() const {
232 switch (type_) {
233 case kTypeGSM:
Darin Petkov9bac6fe2011-08-26 12:49:05 -0700234 if (gsm_.registration_state == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME ||
235 gsm_.registration_state == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING) {
236 switch (gsm_.access_technology) {
237 case MM_MODEM_GSM_ACCESS_TECH_GSM:
238 case MM_MODEM_GSM_ACCESS_TECH_GSM_COMPACT:
Darin Petkove1a3e242011-08-29 12:44:30 -0700239 return flimflam::kNetworkTechnologyGsm;
Darin Petkov9bac6fe2011-08-26 12:49:05 -0700240 case MM_MODEM_GSM_ACCESS_TECH_GPRS:
241 return flimflam::kNetworkTechnologyGprs;
242 case MM_MODEM_GSM_ACCESS_TECH_EDGE:
243 return flimflam::kNetworkTechnologyEdge;
244 case MM_MODEM_GSM_ACCESS_TECH_UMTS:
245 return flimflam::kNetworkTechnologyUmts;
246 case MM_MODEM_GSM_ACCESS_TECH_HSDPA:
247 case MM_MODEM_GSM_ACCESS_TECH_HSUPA:
248 case MM_MODEM_GSM_ACCESS_TECH_HSPA:
249 return flimflam::kNetworkTechnologyHspa;
250 case MM_MODEM_GSM_ACCESS_TECH_HSPA_PLUS:
251 return flimflam::kNetworkTechnologyHspaPlus;
252 default:
253 NOTREACHED();
254 }
255 }
Darin Petkovd2045802011-08-23 11:09:25 -0700256 break;
257 case kTypeCDMA:
258 if (cdma_.registration_state_evdo !=
259 MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN) {
260 return flimflam::kNetworkTechnologyEvdo;
261 }
262 if (cdma_.registration_state_1x !=
263 MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN) {
264 return flimflam::kNetworkTechnology1Xrtt;
265 }
266 break;
267 default:
268 NOTREACHED();
269 }
270 return "";
271}
272
273string Cellular::GetRoamingStateString() const {
274 switch (type_) {
275 case kTypeGSM:
Darin Petkov9bac6fe2011-08-26 12:49:05 -0700276 switch (gsm_.registration_state) {
277 case MM_MODEM_GSM_NETWORK_REG_STATUS_HOME:
278 return flimflam::kRoamingStateHome;
279 case MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING:
280 return flimflam::kRoamingStateRoaming;
281 default:
282 break;
283 }
Darin Petkovd2045802011-08-23 11:09:25 -0700284 break;
285 case kTypeCDMA: {
286 uint32 state = cdma_.registration_state_evdo;
287 if (state == MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN) {
288 state = cdma_.registration_state_1x;
289 }
290 switch (state) {
291 case MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN:
292 case MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED:
293 break;
294 case MM_MODEM_CDMA_REGISTRATION_STATE_HOME:
295 return flimflam::kRoamingStateHome;
296 case MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING:
297 return flimflam::kRoamingStateRoaming;
298 default:
299 NOTREACHED();
300 }
301 break;
302 }
303 default:
304 NOTREACHED();
305 }
306 return flimflam::kRoamingStateUnknown;
307}
308
Darin Petkovc408e692011-08-17 13:47:15 -0700309// static
310string Cellular::GetCDMAActivationStateString(uint32 state) {
311 switch (state) {
312 case MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED:
Darin Petkov51489002011-08-18 13:13:20 -0700313 return flimflam::kActivationStateActivated;
Darin Petkovc408e692011-08-17 13:47:15 -0700314 case MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING:
Darin Petkov51489002011-08-18 13:13:20 -0700315 return flimflam::kActivationStateActivating;
Darin Petkovc408e692011-08-17 13:47:15 -0700316 case MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED:
Darin Petkov51489002011-08-18 13:13:20 -0700317 return flimflam::kActivationStateNotActivated;
Darin Petkovc408e692011-08-17 13:47:15 -0700318 case MM_MODEM_CDMA_ACTIVATION_STATE_PARTIALLY_ACTIVATED:
Darin Petkov51489002011-08-18 13:13:20 -0700319 return flimflam::kActivationStatePartiallyActivated;
Darin Petkovc408e692011-08-17 13:47:15 -0700320 default:
Darin Petkov51489002011-08-18 13:13:20 -0700321 return flimflam::kActivationStateUnknown;
322 }
323}
324
325// static
326string Cellular::GetCDMAActivationErrorString(uint32 error) {
327 switch (error) {
328 case MM_MODEM_CDMA_ACTIVATION_ERROR_WRONG_RADIO_INTERFACE:
329 return flimflam::kErrorNeedEvdo;
330 case MM_MODEM_CDMA_ACTIVATION_ERROR_ROAMING:
331 return flimflam::kErrorNeedHomeNetwork;
332 case MM_MODEM_CDMA_ACTIVATION_ERROR_COULD_NOT_CONNECT:
333 case MM_MODEM_CDMA_ACTIVATION_ERROR_SECURITY_AUTHENTICATION_FAILED:
334 case MM_MODEM_CDMA_ACTIVATION_ERROR_PROVISIONING_FAILED:
335 return flimflam::kErrorOtaspFailed;
336 case MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR:
337 return "";
338 case MM_MODEM_CDMA_ACTIVATION_ERROR_NO_SIGNAL:
339 default:
340 return flimflam::kErrorActivationFailed;
Darin Petkovc408e692011-08-17 13:47:15 -0700341 }
342}
343
Darin Petkov0828f5f2011-08-11 10:18:52 -0700344void Cellular::SetState(State state) {
Darin Petkovcc044422011-08-17 13:30:06 -0700345 VLOG(2) << GetStateString(state_) << " -> " << GetStateString(state);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700346 state_ = state;
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700347}
348
349void Cellular::Start() {
Darin Petkovcc044422011-08-17 13:30:06 -0700350 LOG(INFO) << __func__ << ": " << GetStateString(state_);
Darin Petkov3335b372011-08-22 11:05:32 -0700351 Device::Start();
Darin Petkovbec79a22011-08-01 14:47:17 -0700352 InitProxies();
Darin Petkovf5f61e02011-07-29 11:35:40 -0700353 EnableModem();
Darin Petkovceb68172011-07-29 14:47:48 -0700354 if (type_ == kTypeGSM) {
355 RegisterGSMModem();
356 }
Darin Petkovf5f61e02011-07-29 11:35:40 -0700357 GetModemStatus();
Darin Petkovceb68172011-07-29 14:47:48 -0700358 GetModemIdentifiers();
359 if (type_ == kTypeGSM) {
360 GetGSMProperties();
361 }
362 GetModemInfo();
363 GetModemRegistrationState();
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700364}
365
366void Cellular::Stop() {
Darin Petkove9d12e02011-07-27 15:09:37 -0700367 proxy_.reset();
Darin Petkove604f702011-07-28 15:51:17 -0700368 simple_proxy_.reset();
Darin Petkovbec79a22011-08-01 14:47:17 -0700369 cdma_proxy_.reset();
Darin Petkove42e1012011-08-31 12:35:04 -0700370 gsm_card_proxy_.reset();
371 gsm_network_proxy_.reset();
Paul Stewartac4ac002011-08-26 12:04:26 -0700372 manager()->DeregisterService(service_);
Darin Petkove9d12e02011-07-27 15:09:37 -0700373 service_ = NULL; // Breaks a reference cycle.
Darin Petkov60b8c3b2011-08-25 11:03:20 -0700374 SelectService(NULL);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700375 SetState(kStateDisabled);
Paul Stewartac4ac002011-08-26 12:04:26 -0700376 RTNLHandler::GetInstance()->SetInterfaceFlags(interface_index(), 0, IFF_UP);
Darin Petkov3335b372011-08-22 11:05:32 -0700377 Device::Stop();
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700378}
379
Darin Petkovbec79a22011-08-01 14:47:17 -0700380void Cellular::InitProxies() {
Darin Petkovcc044422011-08-17 13:30:06 -0700381 VLOG(2) << __func__;
Darin Petkovbec79a22011-08-01 14:47:17 -0700382 proxy_.reset(
Darin Petkovc5f56562011-08-06 16:40:05 -0700383 ProxyFactory::factory()->CreateModemProxy(this, dbus_path_, dbus_owner_));
Darin Petkovbec79a22011-08-01 14:47:17 -0700384 simple_proxy_.reset(
385 ProxyFactory::factory()->CreateModemSimpleProxy(
386 dbus_path_, dbus_owner_));
387 switch (type_) {
388 case kTypeGSM:
Darin Petkov975b5e72011-08-30 11:48:08 -0700389 gsm_card_proxy_.reset(
390 ProxyFactory::factory()->CreateModemGSMCardProxy(
391 this, dbus_path_, dbus_owner_));
Darin Petkova1e0a1c2011-08-25 15:08:33 -0700392 gsm_network_proxy_.reset(
393 ProxyFactory::factory()->CreateModemGSMNetworkProxy(
394 this, dbus_path_, dbus_owner_));
Darin Petkovbec79a22011-08-01 14:47:17 -0700395 break;
396 case kTypeCDMA:
397 cdma_proxy_.reset(
398 ProxyFactory::factory()->CreateModemCDMAProxy(
Darin Petkovd9661952011-08-03 16:25:42 -0700399 this, dbus_path_, dbus_owner_));
Darin Petkovbec79a22011-08-01 14:47:17 -0700400 break;
401 default: NOTREACHED();
402 }
403}
404
Darin Petkovf5f61e02011-07-29 11:35:40 -0700405void Cellular::EnableModem() {
406 CHECK_EQ(kStateDisabled, state_);
407 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
408 proxy_->Enable(true);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700409 SetState(kStateEnabled);
Darin Petkovf5f61e02011-07-29 11:35:40 -0700410}
411
412void Cellular::GetModemStatus() {
Darin Petkovceb68172011-07-29 14:47:48 -0700413 CHECK_EQ(kStateEnabled, state_);
Darin Petkovf5f61e02011-07-29 11:35:40 -0700414 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
415 DBusPropertiesMap properties = simple_proxy_->GetStatus();
Darin Petkovceb68172011-07-29 14:47:48 -0700416 if (DBusProperties::GetString(properties, "carrier", &carrier_) &&
417 type_ == kTypeCDMA) {
Darin Petkov3335b372011-08-22 11:05:32 -0700418 home_provider_.SetName(carrier_);
419 home_provider_.SetCode("");
420 home_provider_.SetCountry("us");
Darin Petkovf5f61e02011-07-29 11:35:40 -0700421 }
Darin Petkovceb68172011-07-29 14:47:48 -0700422 DBusProperties::GetString(properties, "meid", &meid_);
423 DBusProperties::GetString(properties, "imei", &imei_);
424 if (DBusProperties::GetString(properties, "imsi", &imsi_) &&
425 type_ == kTypeGSM) {
426 // TODO(petkov): Set GSM provider.
427 }
428 DBusProperties::GetString(properties, "esn", &esn_);
429 DBusProperties::GetString(properties, "mdn", &mdn_);
430 DBusProperties::GetString(properties, "min", &min_);
Darin Petkovceb68172011-07-29 14:47:48 -0700431 DBusProperties::GetString(
432 properties, "firmware_revision", &firmware_revision_);
Darin Petkovb27e5442011-08-16 14:36:45 -0700433
Darin Petkovd2045802011-08-23 11:09:25 -0700434 uint32 state = 0;
435 if (DBusProperties::GetUint32(properties, "state", &state)) {
436 modem_state_ = static_cast<ModemState>(state);
437 }
Darin Petkovb27e5442011-08-16 14:36:45 -0700438
Darin Petkovceb68172011-07-29 14:47:48 -0700439 if (type_ == kTypeCDMA) {
Darin Petkovc408e692011-08-17 13:47:15 -0700440 DBusProperties::GetUint32(
441 properties, "activation_state", &cdma_.activation_state);
Darin Petkovcc044422011-08-17 13:30:06 -0700442 DBusProperties::GetUint16(properties, "prl_version", &cdma_.prl_version);
Darin Petkovcc044422011-08-17 13:30:06 -0700443 // TODO(petkov): For now, get the payment and usage URLs from ModemManager
444 // to match flimflam. In the future, provide a plugin API to get these
445 // directly from the modem driver.
446 DBusProperties::GetString(properties, "payment_url", &cdma_.payment_url);
447 DBusProperties::GetString(properties, "usage_url", &cdma_.usage_url);
Darin Petkovceb68172011-07-29 14:47:48 -0700448 }
449}
450
451void Cellular::GetModemIdentifiers() {
Darin Petkov975b5e72011-08-30 11:48:08 -0700452 VLOG(2) << __func__;
453 switch (type_) {
454 case kTypeGSM:
455 GetGSMIdentifiers();
456 break;
457 case kTypeCDMA:
458 GetCDMAIdentifiers();
459 break;
460 default: NOTREACHED();
461 }
462}
463
464void Cellular::GetCDMAIdentifiers() {
465 CHECK_EQ(kTypeCDMA, type_);
466 if (meid_.empty()) {
467 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
468 meid_ = cdma_proxy_->MEID();
469 VLOG(2) << "MEID: " << imei_;
470 }
471}
472
473void Cellular::GetGSMIdentifiers() {
474 CHECK_EQ(kTypeGSM, type_);
475 if (imei_.empty()) {
476 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
477 imei_ = gsm_card_proxy_->GetIMEI();
478 VLOG(2) << "IMEI: " << imei_;
479 }
480 if (imsi_.empty()) {
481 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
482 imsi_ = gsm_card_proxy_->GetIMSI();
483 VLOG(2) << "IMSI: " << imsi_;
484 }
485 if (gsm_.spn.empty()) {
486 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
487 try {
488 gsm_.spn = gsm_card_proxy_->GetSPN();
489 VLOG(2) << "SPN: " << gsm_.spn;
490 } catch (const DBus::Error e) {
491 // Some modems don't support this call so catch the exception explicitly.
492 LOG(WARNING) << "Unable to obtain SPN: " << e.what();
493 }
494 }
495 if (mdn_.empty()) {
496 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
497 mdn_ = gsm_card_proxy_->GetMSISDN();
498 VLOG(2) << "MSISDN/MDN: " << mdn_;
499 }
Darin Petkovceb68172011-07-29 14:47:48 -0700500}
501
502void Cellular::GetGSMProperties() {
Darin Petkov975b5e72011-08-30 11:48:08 -0700503 CHECK_EQ(kTypeGSM, type_);
Darin Petkov9bac6fe2011-08-26 12:49:05 -0700504 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
505 gsm_.access_technology = gsm_network_proxy_->AccessTechnology();
506 VLOG(2) << "GSM AccessTechnology: " << gsm_.access_technology;
Darin Petkovceb68172011-07-29 14:47:48 -0700507}
508
509void Cellular::RegisterGSMModem() {
Darin Petkov975b5e72011-08-30 11:48:08 -0700510 CHECK_EQ(kTypeGSM, type_);
Darin Petkov9ae310f2011-08-30 15:41:13 -0700511 LOG(INFO) << "Registering on \"" << selected_network_ << "\"";
Darin Petkova1e0a1c2011-08-25 15:08:33 -0700512 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
513 gsm_network_proxy_->Register(selected_network_);
Darin Petkov9ae310f2011-08-30 15:41:13 -0700514 // TODO(petkov): Handle registration failure including trying the home network
515 // when selected_network_ is not empty.
516}
517
518void Cellular::RegisterOnNetwork(const string &network_id, Error *error) {
519 LOG(INFO) << __func__ << "(" << network_id << ")";
520 if (type_ != kTypeGSM) {
521 const string kMessage = "Network registration supported only for GSM.";
522 LOG(ERROR) << kMessage;
523 CHECK(error);
524 error->Populate(Error::kNotSupported, kMessage);
525 return;
526 }
527 // Defer registration because we may be in a dbus-c++ callback.
528 dispatcher()->PostTask(
529 task_factory_.NewRunnableMethod(&Cellular::RegisterOnNetworkTask,
530 network_id));
531}
532
533void Cellular::RegisterOnNetworkTask(const string &network_id) {
534 LOG(INFO) << __func__ << "(" << network_id << ")";
Darin Petkove42e1012011-08-31 12:35:04 -0700535 CHECK_EQ(kTypeGSM, type_);
Darin Petkov9ae310f2011-08-30 15:41:13 -0700536 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
537 gsm_network_proxy_->Register(network_id);
538 // TODO(petkov): Handle registration failure.
539 selected_network_ = network_id;
Darin Petkovceb68172011-07-29 14:47:48 -0700540}
541
Darin Petkove42e1012011-08-31 12:35:04 -0700542void Cellular::RequirePIN(const string &pin, bool require, Error *error) {
543 VLOG(2) << __func__ << "(" << pin << ", " << require << ")";
544 if (type_ != kTypeGSM) {
545 const string kMessage = "RequirePIN supported only for GSM.";
546 LOG(ERROR) << kMessage;
547 CHECK(error);
548 error->Populate(Error::kNotSupported, kMessage);
549 return;
550 }
551 // Defer registration because we may be in a dbus-c++ callback.
552 dispatcher()->PostTask(
553 task_factory_.NewRunnableMethod(&Cellular::RequirePINTask, pin, require));
554}
555
556void Cellular::RequirePINTask(const string &pin, bool require) {
557 VLOG(2) << __func__ << "(" << pin << ", " << require << ")";
558 CHECK_EQ(kTypeGSM, type_);
559 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
560 gsm_card_proxy_->EnablePIN(pin, require);
561}
562
563void Cellular::EnterPIN(const string &pin, Error *error) {
564 VLOG(2) << __func__ << "(" << pin << ")";
565 if (type_ != kTypeGSM) {
566 const string kMessage = "EnterPIN supported only for GSM.";
567 LOG(ERROR) << kMessage;
568 CHECK(error);
569 error->Populate(Error::kNotSupported, kMessage);
570 return;
571 }
572 // Defer registration because we may be in a dbus-c++ callback.
573 dispatcher()->PostTask(
574 task_factory_.NewRunnableMethod(&Cellular::EnterPINTask, pin));
575}
576
577void Cellular::EnterPINTask(const string &pin) {
578 VLOG(2) << __func__ << "(" << pin << ")";
579 CHECK_EQ(kTypeGSM, type_);
580 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
581 gsm_card_proxy_->SendPIN(pin);
582}
583
584void Cellular::UnblockPIN(const string &unblock_code,
585 const string &pin,
586 Error *error) {
587 VLOG(2) << __func__ << "(" << unblock_code << ", " << pin << ")";
588 if (type_ != kTypeGSM) {
589 const string kMessage = "UnblockPIN supported only for GSM.";
590 LOG(ERROR) << kMessage;
591 CHECK(error);
592 error->Populate(Error::kNotSupported, kMessage);
593 return;
594 }
595 // Defer registration because we may be in a dbus-c++ callback.
596 dispatcher()->PostTask(
597 task_factory_.NewRunnableMethod(
598 &Cellular::UnblockPINTask, unblock_code, pin));
599}
600
601void Cellular::UnblockPINTask(const string &unblock_code, const string &pin) {
602 VLOG(2) << __func__ << "(" << unblock_code << ", " << pin << ")";
603 CHECK_EQ(kTypeGSM, type_);
604 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
605 gsm_card_proxy_->SendPUK(unblock_code, pin);
606}
607
608void Cellular::ChangePIN(const string &old_pin,
609 const string &new_pin,
610 Error *error) {
611 VLOG(2) << __func__ << "(" << old_pin << ", " << new_pin << ")";
612 if (type_ != kTypeGSM) {
613 const string kMessage = "ChangePIN supported only for GSM.";
614 LOG(ERROR) << kMessage;
615 CHECK(error);
616 error->Populate(Error::kNotSupported, kMessage);
617 return;
618 }
619 // Defer registration because we may be in a dbus-c++ callback.
620 dispatcher()->PostTask(
621 task_factory_.NewRunnableMethod(
622 &Cellular::ChangePINTask, old_pin, new_pin));
623}
624
625void Cellular::ChangePINTask(const string &old_pin, const string &new_pin) {
626 VLOG(2) << __func__ << "(" << old_pin << ", " << new_pin << ")";
627 CHECK_EQ(kTypeGSM, type_);
628 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
629 gsm_card_proxy_->ChangePIN(old_pin, new_pin);
630}
631
Darin Petkovceb68172011-07-29 14:47:48 -0700632void Cellular::GetModemInfo() {
Darin Petkovd2045802011-08-23 11:09:25 -0700633 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Darin Petkovceb68172011-07-29 14:47:48 -0700634 ModemProxyInterface::Info info = proxy_->GetInfo();
635 manufacturer_ = info._1;
636 model_id_ = info._2;
637 hardware_revision_ = info._3;
638 VLOG(2) << "ModemInfo: " << manufacturer_ << ", " << model_id_ << ", "
639 << hardware_revision_;
640}
641
642void Cellular::GetModemRegistrationState() {
Darin Petkovbec79a22011-08-01 14:47:17 -0700643 switch (type_) {
644 case kTypeGSM:
645 GetGSMRegistrationState();
646 break;
647 case kTypeCDMA:
648 GetCDMARegistrationState();
649 break;
650 default: NOTREACHED();
651 }
Darin Petkovd9661952011-08-03 16:25:42 -0700652 HandleNewRegistrationState();
Darin Petkovbec79a22011-08-01 14:47:17 -0700653}
654
655void Cellular::GetCDMARegistrationState() {
656 CHECK_EQ(kTypeCDMA, type_);
Darin Petkovd2045802011-08-23 11:09:25 -0700657 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Darin Petkovbec79a22011-08-01 14:47:17 -0700658 cdma_proxy_->GetRegistrationState(&cdma_.registration_state_1x,
659 &cdma_.registration_state_evdo);
660 VLOG(2) << "CDMA Registration: 1x(" << cdma_.registration_state_1x
661 << ") EVDO(" << cdma_.registration_state_evdo << ")";
Darin Petkovbec79a22011-08-01 14:47:17 -0700662}
663
664void Cellular::GetGSMRegistrationState() {
Darin Petkov9bac6fe2011-08-26 12:49:05 -0700665 CHECK_EQ(kTypeGSM, type_);
666 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
667 ModemGSMNetworkProxyInterface::RegistrationInfo info =
668 gsm_network_proxy_->GetRegistrationInfo();
669 gsm_.registration_state = info._1;
670 gsm_.network_id = info._2;
671 gsm_.operator_name = info._3;
672 VLOG(2) << "GSM Registration: " << gsm_.registration_state << ", "
673 << gsm_.network_id << ", " << gsm_.operator_name;
Darin Petkovceb68172011-07-29 14:47:48 -0700674}
675
Darin Petkovd9661952011-08-03 16:25:42 -0700676void Cellular::HandleNewRegistrationState() {
Paul Stewartac4ac002011-08-26 12:04:26 -0700677 dispatcher()->PostTask(
Darin Petkov0828f5f2011-08-11 10:18:52 -0700678 task_factory_.NewRunnableMethod(
679 &Cellular::HandleNewRegistrationStateTask));
680}
681
682void Cellular::HandleNewRegistrationStateTask() {
Darin Petkovd9661952011-08-03 16:25:42 -0700683 VLOG(2) << __func__;
Darin Petkovd2045802011-08-23 11:09:25 -0700684 const string network_tech = GetNetworkTechnologyString();
685 if (network_tech.empty()) {
Darin Petkovc408e692011-08-17 13:47:15 -0700686 if (state_ == kStateLinked) {
Paul Stewartac4ac002011-08-26 12:04:26 -0700687 manager()->DeregisterService(service_);
Darin Petkovc408e692011-08-17 13:47:15 -0700688 }
Darin Petkovd9661952011-08-03 16:25:42 -0700689 service_ = NULL;
Darin Petkov0828f5f2011-08-11 10:18:52 -0700690 if (state_ == kStateLinked ||
691 state_ == kStateConnected ||
692 state_ == kStateRegistered) {
693 SetState(kStateEnabled);
Darin Petkovd9661952011-08-03 16:25:42 -0700694 }
695 return;
696 }
Darin Petkovd9661952011-08-03 16:25:42 -0700697 if (state_ == kStateEnabled) {
Darin Petkov0828f5f2011-08-11 10:18:52 -0700698 SetState(kStateRegistered);
Darin Petkovd9661952011-08-03 16:25:42 -0700699 }
700 if (!service_.get()) {
701 // For now, no endpoint is created. Revisit if necessary.
702 CreateService();
703 }
704 GetModemSignalQuality();
Darin Petkov0828f5f2011-08-11 10:18:52 -0700705 if (state_ == kStateRegistered && modem_state_ == kModemStateConnected) {
706 SetState(kStateConnected);
707 EstablishLink();
708 }
Darin Petkovd2045802011-08-23 11:09:25 -0700709 service_->set_network_tech(network_tech);
710 service_->set_roaming_state(GetRoamingStateString());
Darin Petkov9bac6fe2011-08-26 12:49:05 -0700711 // TODO(petkov): For GSM, update the serving operator based on the network id
712 // and the mobile provider database.
Darin Petkovd9661952011-08-03 16:25:42 -0700713}
714
715void Cellular::GetModemSignalQuality() {
Darin Petkov0828f5f2011-08-11 10:18:52 -0700716 VLOG(2) << __func__;
Darin Petkovd9661952011-08-03 16:25:42 -0700717 uint32 strength = 0;
718 switch (type_) {
719 case kTypeGSM:
720 strength = GetGSMSignalQuality();
721 break;
722 case kTypeCDMA:
723 strength = GetCDMASignalQuality();
724 break;
725 default: NOTREACHED();
726 }
727 HandleNewSignalQuality(strength);
728}
729
730uint32 Cellular::GetCDMASignalQuality() {
Darin Petkov0828f5f2011-08-11 10:18:52 -0700731 VLOG(2) << __func__;
Darin Petkovd9661952011-08-03 16:25:42 -0700732 CHECK_EQ(kTypeCDMA, type_);
733 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
734 return cdma_proxy_->GetSignalQuality();
735}
736
737uint32 Cellular::GetGSMSignalQuality() {
Darin Petkov22b72bf2011-08-29 14:01:20 -0700738 VLOG(2) << __func__;
739 CHECK_EQ(kTypeGSM, type_);
740 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
741 return gsm_network_proxy_->GetSignalQuality();
Darin Petkovd9661952011-08-03 16:25:42 -0700742}
743
744void Cellular::HandleNewSignalQuality(uint32 strength) {
745 VLOG(2) << "Signal strength: " << strength;
746 if (service_.get()) {
747 service_->set_strength(strength);
748 }
749}
750
751void Cellular::CreateService() {
Darin Petkov0828f5f2011-08-11 10:18:52 -0700752 VLOG(2) << __func__;
Darin Petkovd9661952011-08-03 16:25:42 -0700753 CHECK(!service_.get());
754 service_ =
Paul Stewartac4ac002011-08-26 12:04:26 -0700755 new CellularService(control_interface(), dispatcher(), manager(), this);
Darin Petkovc408e692011-08-17 13:47:15 -0700756 switch (type_) {
757 case kTypeGSM:
Darin Petkov51489002011-08-18 13:13:20 -0700758 service_->set_activation_state(flimflam::kActivationStateActivated);
Darin Petkov3335b372011-08-22 11:05:32 -0700759 // TODO(petkov): Set serving operator.
Darin Petkovc408e692011-08-17 13:47:15 -0700760 break;
761 case kTypeCDMA:
762 service_->set_payment_url(cdma_.payment_url);
763 service_->set_usage_url(cdma_.usage_url);
Darin Petkov3335b372011-08-22 11:05:32 -0700764 service_->set_serving_operator(home_provider_);
Darin Petkovc408e692011-08-17 13:47:15 -0700765 HandleNewCDMAActivationState(MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR);
766 break;
767 default:
768 NOTREACHED();
Darin Petkovcc044422011-08-17 13:30:06 -0700769 }
Darin Petkovf5f61e02011-07-29 11:35:40 -0700770}
771
Darin Petkov6f9eaa32011-08-09 15:26:44 -0700772bool Cellular::TechnologyIs(const Device::Technology type) const {
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700773 return type == Device::kCellular;
774}
775
Darin Petkov4d6d9412011-08-24 13:19:54 -0700776void Cellular::Connect(Error *error) {
Darin Petkovc5f56562011-08-06 16:40:05 -0700777 VLOG(2) << __func__;
Darin Petkov0828f5f2011-08-11 10:18:52 -0700778 if (state_ == kStateConnected ||
779 state_ == kStateLinked) {
Darin Petkov4d6d9412011-08-24 13:19:54 -0700780 LOG(ERROR) << "Already connected; connection request ignored.";
781 CHECK(error);
782 error->Populate(Error::kAlreadyConnected);
Darin Petkovc5f56562011-08-06 16:40:05 -0700783 return;
784 }
785 CHECK_EQ(kStateRegistered, state_);
Darin Petkovd2045802011-08-23 11:09:25 -0700786
787 if (!allow_roaming_ &&
788 service_->roaming_state() == flimflam::kRoamingStateRoaming) {
789 LOG(ERROR) << "Roaming disallowed; connection request ignored.";
Darin Petkov4d6d9412011-08-24 13:19:54 -0700790 CHECK(error);
791 error->Populate(Error::kNotOnHomeNetwork);
Darin Petkovd2045802011-08-23 11:09:25 -0700792 return;
793 }
794
Darin Petkovc5f56562011-08-06 16:40:05 -0700795 DBusPropertiesMap properties;
796 const char *phone_number = NULL;
797 switch (type_) {
798 case kTypeGSM:
799 phone_number = kPhoneNumberGSM;
800 break;
801 case kTypeCDMA:
802 phone_number = kPhoneNumberCDMA;
803 break;
804 default: NOTREACHED();
805 }
806 properties[kConnectPropertyPhoneNumber].writer().append_string(phone_number);
807 // TODO(petkov): Setup apn and "home_only".
808
809 // Defer connect because we may be in a dbus-c++ callback.
Paul Stewartac4ac002011-08-26 12:04:26 -0700810 dispatcher()->PostTask(
Darin Petkovc5f56562011-08-06 16:40:05 -0700811 task_factory_.NewRunnableMethod(&Cellular::ConnectTask, properties));
812}
813
814void Cellular::ConnectTask(const DBusPropertiesMap &properties) {
815 VLOG(2) << __func__;
Darin Petkovbac96002011-08-09 13:22:00 -0700816 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
Darin Petkovc5f56562011-08-06 16:40:05 -0700817 simple_proxy_->Connect(properties);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700818 SetState(kStateConnected);
Darin Petkovbac96002011-08-09 13:22:00 -0700819 EstablishLink();
820}
821
822void Cellular::EstablishLink() {
823 VLOG(2) << __func__;
Darin Petkov0828f5f2011-08-11 10:18:52 -0700824 CHECK_EQ(kStateConnected, state_);
825 unsigned int flags = 0;
Paul Stewartac4ac002011-08-26 12:04:26 -0700826 if (manager()->device_info()->GetFlags(interface_index(), &flags) &&
Darin Petkov0828f5f2011-08-11 10:18:52 -0700827 (flags & IFF_UP) != 0) {
828 LinkEvent(flags, IFF_UP);
829 return;
830 }
831 // TODO(petkov): Provide a timeout for a failed link-up request.
832 RTNLHandler::GetInstance()->SetInterfaceFlags(
Paul Stewartac4ac002011-08-26 12:04:26 -0700833 interface_index(), IFF_UP, IFF_UP);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700834}
835
836void Cellular::LinkEvent(unsigned int flags, unsigned int change) {
837 Device::LinkEvent(flags, change);
838 if ((flags & IFF_UP) != 0 && state_ == kStateConnected) {
Paul Stewartac4ac002011-08-26 12:04:26 -0700839 LOG(INFO) << link_name() << " is up.";
Darin Petkov0828f5f2011-08-11 10:18:52 -0700840 SetState(kStateLinked);
Paul Stewartac4ac002011-08-26 12:04:26 -0700841 manager()->RegisterService(service_);
Darin Petkov0828f5f2011-08-11 10:18:52 -0700842 // TODO(petkov): For GSM, remember the APN.
Darin Petkov60b8c3b2011-08-25 11:03:20 -0700843 if (AcquireDHCPConfig()) {
844 SelectService(service_);
845 SetServiceState(Service::kStateConfiguring);
846 } else {
847 LOG(ERROR) << "Unable to acquire DHCP config.";
848 }
Darin Petkov0828f5f2011-08-11 10:18:52 -0700849 } else if ((flags & IFF_UP) == 0 && state_ == kStateLinked) {
850 SetState(kStateConnected);
Paul Stewartac4ac002011-08-26 12:04:26 -0700851 manager()->DeregisterService(service_);
Darin Petkov60b8c3b2011-08-25 11:03:20 -0700852 SelectService(NULL);
Darin Petkov77cb6812011-08-15 16:19:41 -0700853 DestroyIPConfig();
Darin Petkov0828f5f2011-08-11 10:18:52 -0700854 }
Darin Petkovc5f56562011-08-06 16:40:05 -0700855}
856
Darin Petkovb100ae72011-08-24 16:19:45 -0700857void Cellular::Activate(const string &carrier, Error *error) {
858 if (type_ != kTypeCDMA) {
859 const string kMessage = "Unable to activate non-CDMA modem.";
860 LOG(ERROR) << kMessage;
861 CHECK(error);
862 error->Populate(Error::kInvalidArguments, kMessage);
863 return;
864 }
865 if (state_ != kStateEnabled &&
866 state_ != kStateRegistered) {
867 const string kMessage = "Unable to activate in " + GetStateString(state_);
868 LOG(ERROR) << kMessage;
869 CHECK(error);
870 error->Populate(Error::kInvalidArguments, kMessage);
871 return;
872 }
Darin Petkovc408e692011-08-17 13:47:15 -0700873 // Defer connect because we may be in a dbus-c++ callback.
Paul Stewartac4ac002011-08-26 12:04:26 -0700874 dispatcher()->PostTask(
Darin Petkovc408e692011-08-17 13:47:15 -0700875 task_factory_.NewRunnableMethod(&Cellular::ActivateTask, carrier));
876}
877
878void Cellular::ActivateTask(const string &carrier) {
879 VLOG(2) << __func__ << "(" << carrier << ")";
Darin Petkovb100ae72011-08-24 16:19:45 -0700880 if (state_ != kStateEnabled &&
881 state_ != kStateRegistered) {
Darin Petkovc408e692011-08-17 13:47:15 -0700882 LOG(ERROR) << "Unable to activate in " << GetStateString(state_);
883 return;
884 }
885 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
886 uint32 status = cdma_proxy_->Activate(carrier);
887 if (status == MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR) {
888 cdma_.activation_state = MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING;
889 }
890 HandleNewCDMAActivationState(status);
891}
892
893void Cellular::HandleNewCDMAActivationState(uint32 error) {
894 if (!service_.get()) {
895 return;
896 }
897 service_->set_activation_state(
898 GetCDMAActivationStateString(cdma_.activation_state));
Darin Petkov51489002011-08-18 13:13:20 -0700899 service_->set_error(GetCDMAActivationErrorString(error));
Darin Petkovc408e692011-08-17 13:47:15 -0700900}
901
Darin Petkovb27e5442011-08-16 14:36:45 -0700902void Cellular::OnCDMAActivationStateChanged(
903 uint32 activation_state,
904 uint32 activation_error,
905 const DBusPropertiesMap &status_changes) {
906 CHECK_EQ(kTypeCDMA, type_);
907 DBusProperties::GetString(status_changes, "mdn", &mdn_);
908 DBusProperties::GetString(status_changes, "min", &min_);
Darin Petkovcc044422011-08-17 13:30:06 -0700909 if (DBusProperties::GetString(
910 status_changes, "payment_url", &cdma_.payment_url) &&
Darin Petkovb27e5442011-08-16 14:36:45 -0700911 service_.get()) {
Darin Petkovcc044422011-08-17 13:30:06 -0700912 service_->set_payment_url(cdma_.payment_url);
Darin Petkovb27e5442011-08-16 14:36:45 -0700913 }
Darin Petkovc408e692011-08-17 13:47:15 -0700914 cdma_.activation_state = activation_state;
915 HandleNewCDMAActivationState(activation_error);
Darin Petkovb27e5442011-08-16 14:36:45 -0700916}
917
Darin Petkovd9661952011-08-03 16:25:42 -0700918void Cellular::OnCDMARegistrationStateChanged(uint32 state_1x,
919 uint32 state_evdo) {
920 CHECK_EQ(kTypeCDMA, type_);
921 cdma_.registration_state_1x = state_1x;
922 cdma_.registration_state_evdo = state_evdo;
923 HandleNewRegistrationState();
924}
925
926void Cellular::OnCDMASignalQualityChanged(uint32 strength) {
927 CHECK_EQ(kTypeCDMA, type_);
928 HandleNewSignalQuality(strength);
929}
930
Darin Petkova1e0a1c2011-08-25 15:08:33 -0700931void Cellular::OnGSMNetworkModeChanged(uint32 mode) {
932 // TODO(petkov): Implement this.
933 NOTIMPLEMENTED();
934}
935
936void Cellular::OnGSMRegistrationInfoChanged(uint32 status,
937 const string &operator_code,
938 const string &operator_name) {
Darin Petkov9bac6fe2011-08-26 12:49:05 -0700939 CHECK_EQ(kTypeGSM, type_);
940 gsm_.registration_state = status;
941 gsm_.network_id = operator_code;
942 gsm_.operator_name = operator_name;
943 HandleNewRegistrationState();
Darin Petkova1e0a1c2011-08-25 15:08:33 -0700944}
945
946void Cellular::OnGSMSignalQualityChanged(uint32 quality) {
Darin Petkov22b72bf2011-08-29 14:01:20 -0700947 CHECK_EQ(kTypeGSM, type_);
948 HandleNewSignalQuality(quality);
Darin Petkova1e0a1c2011-08-25 15:08:33 -0700949}
950
Darin Petkovc5f56562011-08-06 16:40:05 -0700951void Cellular::OnModemStateChanged(uint32 old_state,
952 uint32 new_state,
953 uint32 reason) {
954 // TODO(petkov): Implement this.
955 NOTIMPLEMENTED();
956}
957
Chris Masone889666b2011-07-03 12:58:50 -0700958Stringmaps Cellular::EnumerateNetworks() {
959 Stringmaps to_return;
960 for (vector<Network>::const_iterator it = found_networks_.begin();
961 it != found_networks_.end();
962 ++it) {
963 to_return.push_back(it->ToDict());
964 }
965 return to_return;
966}
967
968StrIntPair Cellular::SimLockStatusToProperty() {
969 return StrIntPair(make_pair(flimflam::kSIMLockTypeProperty,
970 sim_lock_status_.lock_type),
971 make_pair(flimflam::kSIMLockRetriesLeftProperty,
972 sim_lock_status_.retries_left));
973}
974
975void Cellular::HelpRegisterDerivedStringmaps(
976 const string &name,
977 Stringmaps(Cellular::*get)(void),
978 bool(Cellular::*set)(const Stringmaps&)) {
Paul Stewartac4ac002011-08-26 12:04:26 -0700979 store()->RegisterDerivedStringmaps(
Chris Masone889666b2011-07-03 12:58:50 -0700980 name,
981 StringmapsAccessor(
982 new CustomAccessor<Cellular, Stringmaps>(this, get, set)));
983}
984
985void Cellular::HelpRegisterDerivedStrIntPair(
986 const string &name,
987 StrIntPair(Cellular::*get)(void),
988 bool(Cellular::*set)(const StrIntPair&)) {
Paul Stewartac4ac002011-08-26 12:04:26 -0700989 store()->RegisterDerivedStrIntPair(
Chris Masone889666b2011-07-03 12:58:50 -0700990 name,
991 StrIntPairAccessor(
992 new CustomAccessor<Cellular, StrIntPair>(this, get, set)));
993}
994
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700995} // namespace shill