blob: d0bdd39c5088c5d4270d8c47485091fb100755c9 [file] [log] [blame]
Roshan Pius3c4e8a32016-10-03 14:53:58 -07001/*
2 * Copyright (C) 2016 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 "wifi_chip.h"
18
19#include <android-base/logging.h>
20
21#include "failure_reason_util.h"
22
Roshan Pius35d958c2016-10-06 16:47:38 -070023namespace {
24using android::sp;
25using android::hardware::hidl_vec;
26using android::hardware::hidl_string;
27
28hidl_vec<hidl_string> createHidlVecOfIfaceNames(const std::string& ifname) {
29 std::vector<hidl_string> ifnames;
30 if (!ifname.empty()) {
31 hidl_string hidl_ifname;
32 hidl_ifname = ifname.c_str();
33 ifnames.emplace_back(hidl_ifname);
34 }
35 hidl_vec<hidl_string> hidl_ifnames;
36 hidl_ifnames.setToExternal(ifnames.data(), ifnames.size());
37 return hidl_ifnames;
38}
39
40template <typename Iface>
41void invalidateAndClear(sp<Iface>& iface) {
42 if (iface.get()) {
43 iface->invalidate();
44 iface.clear();
45 }
46}
47} // namepsace
48
Roshan Pius3c4e8a32016-10-03 14:53:58 -070049namespace android {
50namespace hardware {
51namespace wifi {
Roshan Pius79a99752016-10-04 13:03:58 -070052namespace V1_0 {
53namespace implementation {
Roshan Pius3c4e8a32016-10-03 14:53:58 -070054
Roshan Piuscd566bd2016-10-10 08:03:42 -070055WifiChip::WifiChip(ChipId chip_id,
56 const std::weak_ptr<WifiLegacyHal> legacy_hal)
Roshan Pius35d958c2016-10-06 16:47:38 -070057 : chip_id_(chip_id), legacy_hal_(legacy_hal), is_valid_(true) {}
Roshan Pius3c4e8a32016-10-03 14:53:58 -070058
Roshan Piusaabe5752016-09-29 09:03:59 -070059void WifiChip::invalidate() {
Roshan Pius35d958c2016-10-06 16:47:38 -070060 invalidateAndRemoveAllIfaces();
Roshan Piusaabe5752016-09-29 09:03:59 -070061 legacy_hal_.reset();
Roshan Pius3c4e8a32016-10-03 14:53:58 -070062 callbacks_.clear();
Roshan Pius35d958c2016-10-06 16:47:38 -070063 is_valid_ = false;
Roshan Pius3c4e8a32016-10-03 14:53:58 -070064}
65
Roshan Piuscd566bd2016-10-10 08:03:42 -070066Return<ChipId> WifiChip::getId() {
67 return chip_id_;
68}
69
Roshan Pius3c4e8a32016-10-03 14:53:58 -070070Return<void> WifiChip::registerEventCallback(
Roshan Pius79a99752016-10-04 13:03:58 -070071 const sp<IWifiChipEventCallback>& callback) {
Roshan Pius35d958c2016-10-06 16:47:38 -070072 if (!is_valid_)
Roshan Pius79a99752016-10-04 13:03:58 -070073 return Void();
Roshan Pius3c4e8a32016-10-03 14:53:58 -070074 // TODO(b/31632518): remove the callback when the client is destroyed
Roshan Pius35d958c2016-10-06 16:47:38 -070075 callbacks_.emplace_back(callback);
Roshan Pius3c4e8a32016-10-03 14:53:58 -070076 return Void();
77}
78
79Return<void> WifiChip::getAvailableModes(getAvailableModes_cb cb) {
Roshan Pius35d958c2016-10-06 16:47:38 -070080 if (!is_valid_) {
Roshan Pius3c4e8a32016-10-03 14:53:58 -070081 cb(hidl_vec<ChipMode>());
82 return Void();
83 } else {
84 // TODO add implementation
85 return Void();
86 }
87}
88
89Return<void> WifiChip::configureChip(uint32_t /*mode_id*/) {
Roshan Pius35d958c2016-10-06 16:47:38 -070090 if (!is_valid_)
Roshan Pius79a99752016-10-04 13:03:58 -070091 return Void();
Roshan Pius35d958c2016-10-06 16:47:38 -070092
93 invalidateAndRemoveAllIfaces();
Roshan Pius3c4e8a32016-10-03 14:53:58 -070094 // TODO add implementation
95 return Void();
96}
97
98Return<uint32_t> WifiChip::getMode() {
Roshan Pius35d958c2016-10-06 16:47:38 -070099 if (!is_valid_)
Roshan Pius79a99752016-10-04 13:03:58 -0700100 return 0;
Roshan Pius3c4e8a32016-10-03 14:53:58 -0700101 // TODO add implementation
102 return 0;
103}
104
105Return<void> WifiChip::requestChipDebugInfo() {
Roshan Pius35d958c2016-10-06 16:47:38 -0700106 if (!is_valid_)
Roshan Pius79a99752016-10-04 13:03:58 -0700107 return Void();
Roshan Pius4b26c832016-10-03 12:49:58 -0700108
109 IWifiChipEventCallback::ChipDebugInfo result;
110
111 std::pair<wifi_error, std::string> ret =
Roshan Piusab5c4712016-10-06 14:37:15 -0700112 legacy_hal_.lock()->getDriverVersion();
Roshan Pius4b26c832016-10-03 12:49:58 -0700113 if (ret.first != WIFI_SUCCESS) {
114 LOG(ERROR) << "Failed to get driver version: "
115 << LegacyErrorToString(ret.first);
116 return Void();
117 }
118 result.driverDescription = ret.second.c_str();
119
Roshan Piusab5c4712016-10-06 14:37:15 -0700120 ret = legacy_hal_.lock()->getFirmwareVersion();
Roshan Pius4b26c832016-10-03 12:49:58 -0700121 if (ret.first != WIFI_SUCCESS) {
122 LOG(ERROR) << "Failed to get firmware version: "
123 << LegacyErrorToString(ret.first);
124 return Void();
125 }
126 result.firmwareDescription = ret.second.c_str();
127
128 for (const auto& callback : callbacks_) {
129 callback->onChipDebugInfoAvailable(result);
130 }
Roshan Pius3c4e8a32016-10-03 14:53:58 -0700131 return Void();
132}
133
134Return<void> WifiChip::requestDriverDebugDump() {
Roshan Pius35d958c2016-10-06 16:47:38 -0700135 if (!is_valid_)
Roshan Piuscdb77f32016-10-03 14:09:57 -0700136 return Void();
137
138 std::pair<wifi_error, std::vector<char>> ret =
Roshan Piusab5c4712016-10-06 14:37:15 -0700139 legacy_hal_.lock()->requestDriverMemoryDump();
Roshan Piuscdb77f32016-10-03 14:09:57 -0700140 if (ret.first != WIFI_SUCCESS) {
141 LOG(ERROR) << "Failed to get driver debug dump: "
142 << LegacyErrorToString(ret.first);
143 return Void();
144 }
145
146 auto& driver_dump = ret.second;
147 hidl_vec<uint8_t> hidl_data;
148 hidl_data.setToExternal(reinterpret_cast<uint8_t*>(driver_dump.data()),
149 driver_dump.size());
150 for (const auto& callback : callbacks_) {
151 callback->onDriverDebugDumpAvailable(hidl_data);
152 }
Roshan Pius3c4e8a32016-10-03 14:53:58 -0700153 return Void();
154}
155
156Return<void> WifiChip::requestFirmwareDebugDump() {
Roshan Pius35d958c2016-10-06 16:47:38 -0700157 if (!is_valid_)
Roshan Piuscdb77f32016-10-03 14:09:57 -0700158 return Void();
159
160 std::pair<wifi_error, std::vector<char>> ret =
Roshan Piusab5c4712016-10-06 14:37:15 -0700161 legacy_hal_.lock()->requestFirmwareMemoryDump();
Roshan Piuscdb77f32016-10-03 14:09:57 -0700162 if (ret.first != WIFI_SUCCESS) {
163 LOG(ERROR) << "Failed to get firmware debug dump: "
164 << LegacyErrorToString(ret.first);
165 return Void();
166 }
167
168 auto& firmware_dump = ret.second;
169 hidl_vec<uint8_t> hidl_data;
170 hidl_data.setToExternal(reinterpret_cast<uint8_t*>(firmware_dump.data()),
171 firmware_dump.size());
172 for (const auto& callback : callbacks_) {
173 callback->onFirmwareDebugDumpAvailable(hidl_data);
174 }
Roshan Pius3c4e8a32016-10-03 14:53:58 -0700175 return Void();
176}
177
Roshan Pius35d958c2016-10-06 16:47:38 -0700178Return<void> WifiChip::createApIface(createApIface_cb cb) {
179 if (!is_valid_) {
180 cb(nullptr);
181 return Void();
182 }
183
184 // TODO(b/31997422): Disallow this based on the chip combination.
185 std::string ifname = legacy_hal_.lock()->getApIfaceName();
186 ap_iface_ = new WifiApIface(ifname, legacy_hal_);
187 cb(ap_iface_);
188 return Void();
189}
190
191Return<void> WifiChip::getApIfaceNames(getApIfaceNames_cb cb) {
192 if (!is_valid_) {
193 cb(hidl_vec<hidl_string>());
194 return Void();
195 }
196
197 std::string ifname;
198 if (ap_iface_.get()) {
199 ifname = legacy_hal_.lock()->getApIfaceName().c_str();
200 }
201 cb(createHidlVecOfIfaceNames(ifname));
202 return Void();
203}
204
205Return<void> WifiChip::getApIface(const hidl_string& ifname, getApIface_cb cb) {
206 if (!is_valid_) {
207 cb(nullptr);
208 return Void();
209 }
210
211 if (ap_iface_.get() &&
212 (ifname.c_str() == legacy_hal_.lock()->getApIfaceName())) {
213 cb(ap_iface_);
214 } else {
215 cb(nullptr);
216 }
217 return Void();
218}
219
220Return<void> WifiChip::createNanIface(createNanIface_cb cb) {
221 if (!is_valid_) {
222 cb(nullptr);
223 return Void();
224 }
225
226 // TODO(b/31997422): Disallow this based on the chip combination.
227 std::string ifname = legacy_hal_.lock()->getNanIfaceName();
228 nan_iface_ = new WifiNanIface(ifname, legacy_hal_);
229 cb(nan_iface_);
230 return Void();
231}
232
233Return<void> WifiChip::getNanIfaceNames(getNanIfaceNames_cb cb) {
234 if (!is_valid_) {
235 cb(hidl_vec<hidl_string>());
236 return Void();
237 }
238
239 std::string ifname;
240 if (nan_iface_.get()) {
241 ifname = legacy_hal_.lock()->getNanIfaceName().c_str();
242 }
243 cb(createHidlVecOfIfaceNames(ifname));
244 return Void();
245}
246
247Return<void> WifiChip::getNanIface(const hidl_string& ifname,
248 getNanIface_cb cb) {
249 if (!is_valid_) {
250 cb(nullptr);
251 return Void();
252 }
253
254 if (nan_iface_.get() &&
255 (ifname.c_str() == legacy_hal_.lock()->getNanIfaceName())) {
256 cb(nan_iface_);
257 } else {
258 cb(nullptr);
259 }
260 return Void();
261}
262
263Return<void> WifiChip::createP2pIface(createP2pIface_cb cb) {
264 if (!is_valid_) {
265 cb(nullptr);
266 return Void();
267 }
268
269 // TODO(b/31997422): Disallow this based on the chip combination.
270 std::string ifname = legacy_hal_.lock()->getP2pIfaceName();
271 p2p_iface_ = new WifiP2pIface(ifname, legacy_hal_);
272 cb(p2p_iface_);
273 return Void();
274}
275
276Return<void> WifiChip::getP2pIfaceNames(getP2pIfaceNames_cb cb) {
277 if (!is_valid_) {
278 cb(hidl_vec<hidl_string>());
279 return Void();
280 }
281
282 std::string ifname;
283 if (p2p_iface_.get()) {
284 ifname = legacy_hal_.lock()->getP2pIfaceName().c_str();
285 }
286 cb(createHidlVecOfIfaceNames(ifname));
287 return Void();
288}
289
290Return<void> WifiChip::getP2pIface(const hidl_string& ifname,
291 getP2pIface_cb cb) {
292 if (!is_valid_) {
293 cb(nullptr);
294 return Void();
295 }
296
297 if (p2p_iface_.get() &&
298 (ifname.c_str() == legacy_hal_.lock()->getP2pIfaceName())) {
299 cb(p2p_iface_);
300 } else {
301 cb(nullptr);
302 }
303 return Void();
304}
305
306Return<void> WifiChip::createStaIface(createStaIface_cb cb) {
307 if (!is_valid_) {
308 cb(nullptr);
309 return Void();
310 }
311
312 // TODO(b/31997422): Disallow this based on the chip combination.
313 std::string ifname = legacy_hal_.lock()->getStaIfaceName();
314 sta_iface_ = new WifiStaIface(ifname, legacy_hal_);
315 cb(sta_iface_);
316 return Void();
317}
318
319Return<void> WifiChip::getStaIfaceNames(getStaIfaceNames_cb cb) {
320 if (!is_valid_) {
321 cb(hidl_vec<hidl_string>());
322 return Void();
323 }
324
325 std::string ifname;
326 if (sta_iface_.get()) {
327 ifname = legacy_hal_.lock()->getStaIfaceName().c_str();
328 }
329 cb(createHidlVecOfIfaceNames(ifname));
330 return Void();
331}
332
333Return<void> WifiChip::getStaIface(const hidl_string& ifname,
334 getStaIface_cb cb) {
335 if (!is_valid_) {
336 cb(nullptr);
337 return Void();
338 }
339
340 if (sta_iface_.get() &&
341 (ifname.c_str() == legacy_hal_.lock()->getStaIfaceName())) {
342 cb(sta_iface_);
343 } else {
344 cb(nullptr);
345 }
346 return Void();
347}
348
349void WifiChip::invalidateAndRemoveAllIfaces() {
350 invalidateAndClear(ap_iface_);
351 invalidateAndClear(nan_iface_);
352 invalidateAndClear(p2p_iface_);
353 invalidateAndClear(sta_iface_);
354}
355
Roshan Pius79a99752016-10-04 13:03:58 -0700356} // namespace implementation
357} // namespace V1_0
Roshan Pius3c4e8a32016-10-03 14:53:58 -0700358} // namespace wifi
359} // namespace hardware
360} // namespace android