1 //
2 // Copyright (C) 2012 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #include "shill/cellular/modem_manager.h"
18 
19 #include <base/stl_util.h>
20 #include <mm/mm-modem.h>
21 
22 #include "shill/cellular/modem.h"
23 #include "shill/cellular/modem_manager_proxy_interface.h"
24 #include "shill/control_interface.h"
25 #include "shill/error.h"
26 #include "shill/logging.h"
27 #include "shill/manager.h"
28 
29 using std::string;
30 using std::shared_ptr;
31 using std::vector;
32 
33 namespace shill {
34 
ModemManager(ControlInterface * control_interface,const string & service,const string & path,ModemInfo * modem_info)35 ModemManager::ModemManager(ControlInterface* control_interface,
36                            const string& service,
37                            const string& path,
38                            ModemInfo* modem_info)
39     : control_interface_(control_interface),
40       service_(service),
41       path_(path),
42       service_connected_(false),
43       modem_info_(modem_info) {}
44 
~ModemManager()45 ModemManager::~ModemManager() {}
46 
Connect()47 void ModemManager::Connect() {
48   // Inheriting classes call this superclass method.
49   service_connected_ = true;
50 }
51 
Disconnect()52 void ModemManager::Disconnect() {
53   // Inheriting classes call this superclass method.
54   modems_.clear();
55   service_connected_ = false;
56 }
57 
OnAppeared()58 void ModemManager::OnAppeared() {
59   LOG(INFO) << "Modem manager " << service_ << " appeared.";
60   Connect();
61 }
62 
OnVanished()63 void ModemManager::OnVanished() {
64   LOG(INFO) << "Modem manager " << service_ << " vanished.";
65   Disconnect();
66 }
67 
ModemExists(const std::string & path) const68 bool ModemManager::ModemExists(const std::string& path) const {
69   CHECK(service_connected_);
70   if (ContainsKey(modems_, path)) {
71     LOG(INFO) << "ModemExists: " << path << " already exists.";
72     return true;
73   } else {
74     return false;
75   }
76 }
77 
RecordAddedModem(shared_ptr<Modem> modem)78 void ModemManager::RecordAddedModem(shared_ptr<Modem> modem) {
79   modems_[modem->path()] = modem;
80 }
81 
RemoveModem(const string & path)82 void ModemManager::RemoveModem(const string& path) {
83   LOG(INFO) << "Remove modem: " << path;
84   CHECK(service_connected_);
85   modems_.erase(path);
86 }
87 
OnDeviceInfoAvailable(const string & link_name)88 void ModemManager::OnDeviceInfoAvailable(const string& link_name) {
89   for (Modems::const_iterator it = modems_.begin(); it != modems_.end(); ++it) {
90     it->second->OnDeviceInfoAvailable(link_name);
91   }
92 }
93 
94 // ModemManagerClassic
ModemManagerClassic(ControlInterface * control_interface,const string & service,const string & path,ModemInfo * modem_info)95 ModemManagerClassic::ModemManagerClassic(
96     ControlInterface* control_interface,
97     const string& service,
98     const string& path,
99     ModemInfo* modem_info)
100     : ModemManager(control_interface, service, path, modem_info) {}
101 
~ModemManagerClassic()102 ModemManagerClassic::~ModemManagerClassic() {
103   Stop();
104 }
105 
Start()106 void ModemManagerClassic::Start() {
107   LOG(INFO) << "Start watching modem manager service: " << service();
108   CHECK(!proxy_);
109   proxy_.reset(
110       control_interface()->CreateModemManagerProxy(
111           this,
112           path(),
113           service(),
114           base::Bind(&ModemManagerClassic::OnAppeared, base::Unretained(this)),
115           base::Bind(&ModemManagerClassic::OnVanished,
116                      base::Unretained(this))));
117 }
118 
Stop()119 void ModemManagerClassic::Stop() {
120   LOG(INFO) << "Stop watching modem manager service: " << service();
121   proxy_.reset();
122   Disconnect();
123 }
124 
Connect()125 void ModemManagerClassic::Connect() {
126   ModemManager::Connect();
127   // TODO(petkov): Switch to asynchronous calls (crbug.com/200687).
128   vector<string> devices = proxy_->EnumerateDevices();
129 
130   for (vector<string>::const_iterator it = devices.begin();
131        it != devices.end(); ++it) {
132     AddModemClassic(*it);
133   }
134 }
135 
AddModemClassic(const string & path)136 void ModemManagerClassic::AddModemClassic(const string& path) {
137   if (ModemExists(path)) {
138     return;
139   }
140   shared_ptr<ModemClassic> modem(new ModemClassic(service(),
141                                                   path,
142                                                   modem_info(),
143                                                   control_interface()));
144   RecordAddedModem(modem);
145   InitModemClassic(modem);
146 }
147 
Disconnect()148 void ModemManagerClassic::Disconnect() {
149   ModemManager::Disconnect();
150 }
151 
InitModemClassic(shared_ptr<ModemClassic> modem)152 void ModemManagerClassic::InitModemClassic(shared_ptr<ModemClassic> modem) {
153   // TODO(rochberg): Switch to asynchronous calls (crbug.com/200687).
154   if (modem == nullptr) {
155     return;
156   }
157 
158   std::unique_ptr<DBusPropertiesProxyInterface> properties_proxy(
159       control_interface()->CreateDBusPropertiesProxy(modem->path(),
160                                                      modem->service()));
161   KeyValueStore properties =
162       properties_proxy->GetAll(MM_MODEM_INTERFACE);
163 
164   modem->CreateDeviceClassic(properties);
165 }
166 
OnDeviceAdded(const string & path)167 void ModemManagerClassic::OnDeviceAdded(const string& path) {
168   AddModemClassic(path);
169 }
170 
OnDeviceRemoved(const string & path)171 void ModemManagerClassic::OnDeviceRemoved(const string& path) {
172   RemoveModem(path);
173 }
174 
175 }  // namespace shill
176