blob: 9aedd835f69fd824ae319feb5e643e81f754f487 [file] [log] [blame]
Darin Petkov41c0e0a2012-01-09 16:38:53 +01001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Darin Petkov887f2982011-07-14 16:10:17 -07002// 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/modem_manager.h"
6
David Rochberg7cb06f62012-03-05 11:23:44 -05007#include <algorithm>
8
Eric Shienbrood9a245532012-03-07 14:20:39 -05009#include <base/bind.h>
Darin Petkov887f2982011-07-14 16:10:17 -070010#include <base/logging.h>
Eric Shienbrood3e20a232012-02-16 11:35:56 -050011#include <base/stl_util.h>
Darin Petkov887f2982011-07-14 16:10:17 -070012
Eric Shienbrood9a245532012-03-07 14:20:39 -050013#include "shill/error.h"
Darin Petkov5c97ac52011-07-19 16:30:49 -070014#include "shill/modem.h"
Darin Petkovc90fe522011-07-15 13:59:47 -070015#include "shill/modem_manager_proxy.h"
16#include "shill/proxy_factory.h"
17
Eric Shienbrood9a245532012-03-07 14:20:39 -050018using base::Bind;
Darin Petkov887f2982011-07-14 16:10:17 -070019using std::string;
Darin Petkov5c97ac52011-07-19 16:30:49 -070020using std::tr1::shared_ptr;
21using std::vector;
Darin Petkov887f2982011-07-14 16:10:17 -070022
23namespace shill {
Darin Petkov887f2982011-07-14 16:10:17 -070024ModemManager::ModemManager(const string &service,
25 const string &path,
26 ControlInterface *control_interface,
27 EventDispatcher *dispatcher,
Thieu Le3426c8f2012-01-11 17:35:11 -080028 Metrics *metrics,
Darin Petkov887f2982011-07-14 16:10:17 -070029 Manager *manager,
Darin Petkov137884a2011-10-26 18:52:47 +020030 GLib *glib,
31 mobile_provider_db *provider_db)
Darin Petkovab565bb2011-10-06 02:55:51 -070032 : proxy_factory_(ProxyFactory::GetInstance()),
33 service_(service),
Darin Petkov887f2982011-07-14 16:10:17 -070034 path_(path),
35 watcher_id_(0),
36 control_interface_(control_interface),
37 dispatcher_(dispatcher),
Thieu Le3426c8f2012-01-11 17:35:11 -080038 metrics_(metrics),
Darin Petkov67d8ecf2011-07-26 16:03:30 -070039 manager_(manager),
Darin Petkov137884a2011-10-26 18:52:47 +020040 glib_(glib),
41 provider_db_(provider_db) {}
Darin Petkov887f2982011-07-14 16:10:17 -070042
43ModemManager::~ModemManager() {
44 Stop();
45}
46
47void ModemManager::Start() {
48 LOG(INFO) << "Start watching modem manager service: " << service_;
Eric Shienbroodc74cf9c2012-03-02 15:00:35 -050049 CHECK_EQ(0U, watcher_id_);
Darin Petkovc90fe522011-07-15 13:59:47 -070050 // TODO(petkov): Implement DBus name watching through dbus-c++.
Darin Petkov887f2982011-07-14 16:10:17 -070051 watcher_id_ = glib_->BusWatchName(G_BUS_TYPE_SYSTEM,
52 service_.c_str(),
53 G_BUS_NAME_WATCHER_FLAGS_NONE,
54 OnAppear,
55 OnVanish,
56 this,
57 NULL);
58}
59
60void ModemManager::Stop() {
61 LOG(INFO) << "Stop watching modem manager service: " << service_;
62 if (watcher_id_) {
63 glib_->BusUnwatchName(watcher_id_);
64 watcher_id_ = 0;
65 }
66 Disconnect();
67}
68
69void ModemManager::Connect(const string &owner) {
David Rochberg81030ea2012-03-02 15:44:25 -050070 // Inheriting classes call this superclass method.
Darin Petkov887f2982011-07-14 16:10:17 -070071 owner_ = owner;
Darin Petkov887f2982011-07-14 16:10:17 -070072}
73
74void ModemManager::Disconnect() {
David Rochberg81030ea2012-03-02 15:44:25 -050075 // Inheriting classes call this superclass method.
Darin Petkov5c97ac52011-07-19 16:30:49 -070076 modems_.clear();
Darin Petkov887f2982011-07-14 16:10:17 -070077 owner_.clear();
Darin Petkov887f2982011-07-14 16:10:17 -070078}
79
mukesh agrawal1830fa12011-09-26 14:31:40 -070080void ModemManager::OnAppear(GDBusConnection */*connection*/,
Darin Petkov887f2982011-07-14 16:10:17 -070081 const gchar *name,
82 const gchar *name_owner,
83 gpointer user_data) {
84 LOG(INFO) << "Modem manager " << name << " appeared. Owner: " << name_owner;
85 ModemManager *manager = reinterpret_cast<ModemManager *>(user_data);
86 manager->Connect(name_owner);
87}
88
mukesh agrawal1830fa12011-09-26 14:31:40 -070089void ModemManager::OnVanish(GDBusConnection */*connection*/,
Darin Petkov887f2982011-07-14 16:10:17 -070090 const gchar *name,
91 gpointer user_data) {
92 LOG(INFO) << "Modem manager " << name << " vanished.";
93 ModemManager *manager = reinterpret_cast<ModemManager *>(user_data);
94 manager->Disconnect();
95}
96
Darin Petkov41c0e0a2012-01-09 16:38:53 +010097void ModemManager::AddModem(const string &path) {
Darin Petkov5c97ac52011-07-19 16:30:49 -070098 LOG(INFO) << "Add modem: " << path;
99 CHECK(!owner_.empty());
100 if (ContainsKey(modems_, path)) {
101 LOG(INFO) << "Modem already exists; ignored.";
102 return;
103 }
Darin Petkov137884a2011-10-26 18:52:47 +0200104 shared_ptr<Modem> modem(new Modem(owner_,
105 path,
106 control_interface_,
107 dispatcher_,
Thieu Le3426c8f2012-01-11 17:35:11 -0800108 metrics_,
Darin Petkov137884a2011-10-26 18:52:47 +0200109 manager_,
110 provider_db_));
Darin Petkov5c97ac52011-07-19 16:30:49 -0700111 modems_[path] = modem;
David Rochberg81030ea2012-03-02 15:44:25 -0500112 InitModem(modem);
Darin Petkov5c97ac52011-07-19 16:30:49 -0700113}
114
Darin Petkov41c0e0a2012-01-09 16:38:53 +0100115void ModemManager::RemoveModem(const string &path) {
Darin Petkov5c97ac52011-07-19 16:30:49 -0700116 LOG(INFO) << "Remove modem: " << path;
117 CHECK(!owner_.empty());
118 modems_.erase(path);
119}
120
Darin Petkov41c0e0a2012-01-09 16:38:53 +0100121void ModemManager::OnDeviceInfoAvailable(const string &link_name) {
David Rochberg81030ea2012-03-02 15:44:25 -0500122 for (Modems::const_iterator it = modems_.begin(); it != modems_.end(); ++it) {
Darin Petkov41c0e0a2012-01-09 16:38:53 +0100123 it->second->OnDeviceInfoAvailable(link_name);
124 }
125}
126
David Rochberg81030ea2012-03-02 15:44:25 -0500127// ModemManagerClassic
David Rochberg7cb06f62012-03-05 11:23:44 -0500128ModemManagerClassic::ModemManagerClassic(const string &service,
129 const string &path,
David Rochberg81030ea2012-03-02 15:44:25 -0500130 ControlInterface *control_interface,
131 EventDispatcher *dispatcher,
132 Metrics *metrics,
133 Manager *manager,
134 GLib *glib,
135 mobile_provider_db *provider_db) :
136 ModemManager(service,
137 path,
138 control_interface,
139 dispatcher,
140 metrics,
141 manager,
142 glib,
143 provider_db) {}
144
145ModemManagerClassic::~ModemManagerClassic() {}
146
147void ModemManagerClassic::Connect(const string &supplied_owner) {
148 ModemManager::Connect(supplied_owner);
149 proxy_.reset(proxy_factory()->CreateModemManagerProxy(this, path(), owner()));
150
151 // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
152 vector<DBus::Path> devices = proxy_->EnumerateDevices();
153 for (vector<DBus::Path>::const_iterator it = devices.begin();
154 it != devices.end(); ++it) {
155 AddModem(*it);
156 }
157}
158
159void ModemManagerClassic::Disconnect() {
160 ModemManager::Disconnect();
161 proxy_.reset();
162}
163
164void ModemManagerClassic::InitModem(shared_ptr<Modem> modem) {
165 modem->Init();
166}
167
David Rochberg7cb06f62012-03-05 11:23:44 -0500168// ModemManager1
169const char ModemManager1::kDBusInterfaceModem[] =
170 "org.freedesktop.ModemManager1.Modem";
171
172ModemManager1::ModemManager1(const string &service,
173 const string &path,
174 ControlInterface *control_interface,
175 EventDispatcher *dispatcher,
176 Metrics *metrics,
177 Manager *manager,
178 GLib *glib,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500179 mobile_provider_db *provider_db)
180 : ModemManager(service,
181 path,
182 control_interface,
183 dispatcher,
184 metrics,
185 manager,
186 glib,
187 provider_db),
188 weak_ptr_factory_(this) {}
David Rochberg7cb06f62012-03-05 11:23:44 -0500189
190ModemManager1::~ModemManager1() {}
191
192void ModemManager1::Connect(const string &supplied_owner) {
193 ModemManager::Connect(supplied_owner);
194 proxy_.reset(
Eric Shienbrood9a245532012-03-07 14:20:39 -0500195 proxy_factory()->CreateDBusObjectManagerProxy(path(), owner()));
196 proxy_->set_interfaces_added_callback(
197 Bind(&ModemManager1::OnInterfacesAddedSignal,
198 weak_ptr_factory_.GetWeakPtr()));
199 proxy_->set_interfaces_removed_callback(
200 Bind(&ModemManager1::OnInterfacesRemovedSignal,
201 weak_ptr_factory_.GetWeakPtr()));
David Rochberg7cb06f62012-03-05 11:23:44 -0500202
203 // TODO(rochberg): Make global kDBusDefaultTimeout and use it here
Eric Shienbrood9a245532012-03-07 14:20:39 -0500204 Error error;
205 proxy_->GetManagedObjects(&error,
206 Bind(&ModemManager1::OnGetManagedObjectsReply,
207 weak_ptr_factory_.GetWeakPtr()),
208 5000);
David Rochberg7cb06f62012-03-05 11:23:44 -0500209}
210
211void ModemManager1::Disconnect() {
212 ModemManager::Disconnect();
213 proxy_.reset();
214}
215
216void ModemManager1::InitModem(shared_ptr<Modem> modem) {
217 LOG(ERROR) << __func__;
218}
219
Eric Shienbrood9a245532012-03-07 14:20:39 -0500220// signal methods
221// Also called by OnGetManagedObjectsReply
222void ModemManager1::OnInterfacesAddedSignal(
David Rochberg7cb06f62012-03-05 11:23:44 -0500223 const ::DBus::Path &object_path,
224 const DBusInterfaceToProperties &interface_to_properties) {
225 if (ContainsKey(interface_to_properties, kDBusInterfaceModem)) {
226 AddModem(object_path);
227 } else {
228 LOG(ERROR) << "Interfaces added, but not modem interface.";
229 }
230}
231
Eric Shienbrood9a245532012-03-07 14:20:39 -0500232void ModemManager1::OnInterfacesRemovedSignal(
David Rochberg7cb06f62012-03-05 11:23:44 -0500233 const ::DBus::Path &object_path,
234 const vector<string> &interfaces) {
235 LOG(INFO) << "MM1: Removing interfaces from " << object_path;
236 if (find(interfaces.begin(),
237 interfaces.end(),
238 kDBusInterfaceModem) != interfaces.end()) {
239 RemoveModem(object_path);
240 } else {
241 // In theory, a modem could drop, say, 3GPP, but not CDMA. In
242 // practice, we don't expect this
243 LOG(ERROR) << "Interfaces removed, but not modem interface";
244 }
245}
246
247// DBusObjectManagerProxy async method call
Eric Shienbrood9a245532012-03-07 14:20:39 -0500248void ModemManager1::OnGetManagedObjectsReply(
David Rochberg7cb06f62012-03-05 11:23:44 -0500249 const DBusObjectsWithProperties &objects,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500250 const Error &error) {
251 if (error.IsSuccess()) {
252 DBusObjectsWithProperties::const_iterator m;
253 for (m = objects.begin(); m != objects.end(); ++m) {
254 OnInterfacesAddedSignal(m->first, m->second);
255 }
David Rochberg7cb06f62012-03-05 11:23:44 -0500256 }
257}
258
Darin Petkov887f2982011-07-14 16:10:17 -0700259} // namespace shill