-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmodem.cc
269 lines (218 loc) · 8.89 KB
/
modem.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "modemfwd/modem.h"
#include <map>
#include <string>
#include <utility>
#include <base/bind.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/memory/ptr_util.h>
#include <base/logging.h>
#include <base/strings/string_util.h>
#include <base/unguessable_token.h>
#include <brillo/dbus/dbus_method_invoker.h>
#include <chromeos/dbus/service_constants.h>
#include <ModemManager/ModemManager.h>
#include "modemfwd/logging.h"
#include "modemfwd/modem_helper.h"
#include "modemmanager/dbus-proxies.h"
namespace {
class Inhibitor {
public:
Inhibitor(std::unique_ptr<org::freedesktop::ModemManager1Proxy> mm_proxy,
const std::string& physdev_uid)
: mm_proxy_(std::move(mm_proxy)), physdev_uid_(physdev_uid) {}
bool SetInhibited(bool inhibited) {
brillo::ErrorPtr error_unused;
return mm_proxy_->InhibitDevice(physdev_uid_, inhibited, &error_unused);
}
private:
std::unique_ptr<org::freedesktop::ModemManager1Proxy> mm_proxy_;
std::string physdev_uid_;
};
std::unique_ptr<Inhibitor> GetInhibitor(
scoped_refptr<dbus::Bus> bus, const dbus::ObjectPath& mm_object_path) {
// Get the MM object backing this modem, and retrieve its Device property.
// This is the mm_physdev_uid we use for inhibition during updates.
auto mm_device = bus->GetObjectProxy(modemmanager::kModemManager1ServiceName,
mm_object_path);
if (!mm_device)
return nullptr;
brillo::ErrorPtr error;
auto resp = brillo::dbus_utils::CallMethodAndBlock(
mm_device, dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGet,
&error, std::string(modemmanager::kModemManager1ModemInterface),
std::string(MM_MODEM_PROPERTY_DEVICE));
if (!resp)
return nullptr;
std::string mm_physdev_uid;
if (!brillo::dbus_utils::ExtractMethodCallResults(resp.get(), &error,
&mm_physdev_uid)) {
return nullptr;
}
EVLOG(1) << "Modem " << mm_object_path.value() << " has physdev UID "
<< mm_physdev_uid;
auto mm_proxy = std::make_unique<org::freedesktop::ModemManager1Proxy>(
bus, modemmanager::kModemManager1ServiceName);
return std::make_unique<Inhibitor>(std::move(mm_proxy), mm_physdev_uid);
}
} // namespace
namespace modemfwd {
class ModemImpl : public Modem {
public:
ModemImpl(const std::string& device_id,
const std::string& equipment_id,
const std::string& carrier_id,
std::unique_ptr<Inhibitor> inhibitor,
ModemHelper* helper)
: device_id_(device_id),
equipment_id_(equipment_id),
carrier_id_(carrier_id),
inhibitor_(std::move(inhibitor)),
helper_(helper) {
if (!helper->GetFirmwareInfo(&installed_firmware_))
LOG(WARNING) << "Could not fetch installed firmware information";
}
ModemImpl(const ModemImpl&) = delete;
ModemImpl& operator=(const ModemImpl&) = delete;
~ModemImpl() override = default;
// modemfwd::Modem overrides.
std::string GetDeviceId() const override { return device_id_; }
std::string GetEquipmentId() const override { return equipment_id_; }
std::string GetCarrierId() const override { return carrier_id_; }
std::string GetMainFirmwareVersion() const override {
return installed_firmware_.main_version;
}
std::string GetCarrierFirmwareId() const override {
return installed_firmware_.carrier_uuid;
}
std::string GetCarrierFirmwareVersion() const override {
return installed_firmware_.carrier_version;
}
bool SetInhibited(bool inhibited) override {
if (!inhibitor_) {
EVLOG(1) << "Inhibiting unavailable on this modem";
return false;
}
return inhibitor_->SetInhibited(inhibited);
}
bool FlashMainFirmware(const base::FilePath& path_to_fw,
const std::string& version) override {
return helper_->FlashMainFirmware(path_to_fw, version);
}
bool FlashCarrierFirmware(const base::FilePath& path_to_fw,
const std::string& version) override {
return helper_->FlashCarrierFirmware(path_to_fw, version);
}
bool ClearAttachAPN(const std::string& carrier_uuid) override {
return helper_->ClearAttachAPN(carrier_uuid);
}
private:
std::string device_id_;
std::string equipment_id_;
std::string carrier_id_;
std::unique_ptr<Inhibitor> inhibitor_;
FirmwareInfo installed_firmware_;
ModemHelper* helper_;
};
std::unique_ptr<Modem> CreateModem(
scoped_refptr<dbus::Bus> bus,
std::unique_ptr<org::chromium::flimflam::DeviceProxy> device,
ModemHelperDirectory* helper_directory) {
std::string object_path = device->GetObjectPath().value();
DVLOG(1) << "Creating modem proxy for " << object_path;
brillo::ErrorPtr error;
brillo::VariantDictionary properties;
if (!device->GetProperties(&properties, &error)) {
LOG(WARNING) << "Could not get properties for modem " << object_path;
return nullptr;
}
// If we don't have a device ID, modemfwd can't do anything with this modem,
// so check it first and just return if we can't find it.
std::string device_id;
if (!properties[shill::kDeviceIdProperty].GetValue(&device_id)) {
LOG(INFO) << "Modem " << object_path << " has no device ID, ignoring";
return nullptr;
}
// Equipment ID is also pretty important since we use it as a stable
// identifier that can distinguish between modems of the same type.
std::string equipment_id;
if (!properties[shill::kEquipmentIdProperty].GetValue(&equipment_id)) {
LOG(INFO) << "Modem " << object_path << " has no equipment ID, ignoring";
return nullptr;
}
// This property may not exist and it's not a big deal if it doesn't.
std::map<std::string, std::string> operator_info;
std::string carrier_id;
if (properties[shill::kHomeProviderProperty].GetValue(&operator_info))
carrier_id = operator_info[shill::kOperatorUuidKey];
// Get a helper object for inhibiting the modem, if possible.
std::unique_ptr<Inhibitor> inhibitor;
std::string mm_object_path;
if (!properties[shill::kDBusObjectProperty].GetValue(&mm_object_path)) {
LOG(INFO) << "Modem " << object_path << " has no ModemManager object";
} else {
inhibitor = GetInhibitor(bus, dbus::ObjectPath(mm_object_path));
}
if (!inhibitor)
LOG(INFO) << "Inhibiting modem " << object_path << " will not be possible";
// Use the device ID to grab a helper.
ModemHelper* helper = helper_directory->GetHelperForDeviceId(device_id);
if (!helper) {
LOG(INFO) << "No helper found to update modems with ID [" << device_id
<< "]";
return nullptr;
}
return std::make_unique<ModemImpl>(device_id, equipment_id, carrier_id,
std::move(inhibitor), helper);
}
// StubModem acts like a modem with a particular device ID but does not
// actually talk to a real modem. This allows us to use it for force-
// flashing.
class StubModem : public Modem {
public:
StubModem(const std::string& device_id, ModemHelper* helper)
: device_id_(device_id),
equipment_id_(base::UnguessableToken().ToString()),
helper_(helper) {}
StubModem(const StubModem&) = delete;
StubModem& operator=(const StubModem&) = delete;
~StubModem() override = default;
// modemfwd::Modem overrides.
std::string GetDeviceId() const override { return device_id_; }
std::string GetEquipmentId() const override { return equipment_id_; }
std::string GetCarrierId() const override { return ""; }
std::string GetMainFirmwareVersion() const override { return ""; }
std::string GetCarrierFirmwareId() const override { return ""; }
std::string GetCarrierFirmwareVersion() const override { return ""; }
bool SetInhibited(bool inhibited) override { return true; }
bool FlashMainFirmware(const base::FilePath& path_to_fw,
const std::string& version) override {
return helper_->FlashMainFirmware(path_to_fw, version);
}
bool FlashCarrierFirmware(const base::FilePath& path_to_fw,
const std::string& version) override {
return helper_->FlashCarrierFirmware(path_to_fw, version);
}
bool ClearAttachAPN(const std::string& carrier_uuid) override {
return helper_->ClearAttachAPN(carrier_uuid);
}
private:
std::string device_id_;
std::string equipment_id_;
ModemHelper* helper_;
};
std::unique_ptr<Modem> CreateStubModem(const std::string& device_id,
ModemHelperDirectory* helper_directory) {
// Use the device ID to grab a helper.
ModemHelper* helper = helper_directory->GetHelperForDeviceId(device_id);
if (!helper) {
LOG(INFO) << "No helper found to update modems with ID [" << device_id
<< "]";
return nullptr;
}
return std::make_unique<StubModem>(device_id, helper);
}
} // namespace modemfwd