blob: 135e2c514da7a22587f4d946808653a6045d4bac [file] [log] [blame]
Roshan Piusaabe5752016-09-29 09:03:59 -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 <array>
18
Roshan Piusaabe5752016-09-29 09:03:59 -070019#include <android-base/logging.h>
20#include <cutils/properties.h>
Roshan Pius908a69a2016-10-03 13:33:23 -070021#include <wifi_system/interface_tool.h>
Roshan Piusaabe5752016-09-29 09:03:59 -070022
Roshan Pius955542e2016-10-28 09:42:44 -070023#include "wifi_legacy_hal.h"
24
25namespace android {
26namespace hardware {
27namespace wifi {
28namespace V1_0 {
29namespace implementation {
30namespace legacy_hal {
Roshan Pius76ff3022016-10-28 10:33:34 -070031// Constants ported over from the legacy HAL calling code
32// (com_android_server_wifi_WifiNative.cpp). This will all be thrown
33// away when this shim layer is replaced by the real vendor
34// implementation.
Roshan Pius511cc492016-10-28 09:54:26 -070035static constexpr uint32_t kMaxVersionStringLength = 256;
Roshan Pius76ff3022016-10-28 10:33:34 -070036static constexpr uint32_t kMaxCachedGscanResults = 64;
37static constexpr uint32_t kMaxGscanFrequenciesForBand = 64;
Roshan Pius7cece412016-10-28 10:38:21 -070038static constexpr uint32_t kLinkLayerStatsDataMpduSizeThreshold = 128;
Roshan Pius8714a3e2016-10-28 10:43:51 -070039static constexpr uint32_t kMaxWakeReasonStatsArraySize = 32;
40static constexpr uint32_t kMaxRingBuffers = 10;
Roshan Pius511cc492016-10-28 09:54:26 -070041
Roshan Piusaabe5752016-09-29 09:03:59 -070042// Legacy HAL functions accept "C" style function pointers, so use global
43// functions to pass to the legacy HAL function and store the corresponding
44// std::function methods to be invoked.
45// Callback to be invoked once |stop| is complete.
46std::function<void(wifi_handle handle)> on_stop_complete_internal_callback;
47void onStopComplete(wifi_handle handle) {
48 if (on_stop_complete_internal_callback) {
49 on_stop_complete_internal_callback(handle);
50 }
51}
Roshan Piuscdb77f32016-10-03 14:09:57 -070052
53// Callback to be invoked for driver dump.
54std::function<void(char*, int)> on_driver_memory_dump_internal_callback;
55void onDriverMemoryDump(char* buffer, int buffer_size) {
56 if (on_driver_memory_dump_internal_callback) {
57 on_driver_memory_dump_internal_callback(buffer, buffer_size);
58 }
59}
60
61// Callback to be invoked for firmware dump.
62std::function<void(char*, int)> on_firmware_memory_dump_internal_callback;
63void onFirmwareMemoryDump(char* buffer, int buffer_size) {
64 if (on_firmware_memory_dump_internal_callback) {
65 on_firmware_memory_dump_internal_callback(buffer, buffer_size);
66 }
67}
Roshan Pius76ff3022016-10-28 10:33:34 -070068
69// Callback to be invoked for Gscan events.
70std::function<void(wifi_request_id, wifi_scan_event)>
71 on_gscan_event_internal_callback;
72void onGscanEvent(wifi_request_id id, wifi_scan_event event) {
73 if (on_gscan_event_internal_callback) {
74 on_gscan_event_internal_callback(id, event);
75 }
76}
77
78// Callback to be invoked for Gscan full results.
79std::function<void(wifi_request_id, wifi_scan_result*, uint32_t)>
80 on_gscan_full_result_internal_callback;
81void onGscanFullResult(wifi_request_id id,
82 wifi_scan_result* result,
83 uint32_t buckets_scanned) {
84 if (on_gscan_full_result_internal_callback) {
85 on_gscan_full_result_internal_callback(id, result, buckets_scanned);
86 }
87}
88
Roshan Pius7cece412016-10-28 10:38:21 -070089// Callback to be invoked for link layer stats results.
90std::function<void((wifi_request_id, wifi_iface_stat*, int, wifi_radio_stat*))>
91 on_link_layer_stats_result_internal_callback;
92void onLinkLayerStatsDataResult(wifi_request_id id,
93 wifi_iface_stat* iface_stat,
94 int num_radios,
95 wifi_radio_stat* radio_stat) {
96 if (on_link_layer_stats_result_internal_callback) {
97 on_link_layer_stats_result_internal_callback(
98 id, iface_stat, num_radios, radio_stat);
99 }
100}
101
Roshan Pius8714a3e2016-10-28 10:43:51 -0700102// Callback to be invoked for ring buffer data indication.
103std::function<void(char*, char*, int, wifi_ring_buffer_status*)>
104 on_ring_buffer_data_internal_callback;
105void onRingBufferData(char* ring_name,
106 char* buffer,
107 int buffer_size,
108 wifi_ring_buffer_status* status) {
109 if (on_ring_buffer_data_internal_callback) {
110 on_ring_buffer_data_internal_callback(
111 ring_name, buffer, buffer_size, status);
112 }
113}
114
Roshan Pius955542e2016-10-28 09:42:44 -0700115// End of the free-standing "C" style callbacks.
Roshan Piusaabe5752016-09-29 09:03:59 -0700116
Roshan Piusaabe5752016-09-29 09:03:59 -0700117WifiLegacyHal::WifiLegacyHal()
118 : global_handle_(nullptr),
119 wlan_interface_handle_(nullptr),
Roshan Pius908a69a2016-10-03 13:33:23 -0700120 awaiting_event_loop_termination_(false) {}
Roshan Piusaabe5752016-09-29 09:03:59 -0700121
122wifi_error WifiLegacyHal::start() {
123 // Ensure that we're starting in a good state.
124 CHECK(!global_handle_ && !wlan_interface_handle_ &&
125 !awaiting_event_loop_termination_);
126
Roshan Pius908a69a2016-10-03 13:33:23 -0700127 android::wifi_system::InterfaceTool if_tool;
Roshan Pius955542e2016-10-28 09:42:44 -0700128 // TODO: Add back the HAL Tool if we need to. All we need from the HAL tool
129 // for now is this function call which we can directly call.
130 wifi_error status = init_wifi_vendor_hal_func_table(&global_func_table_);
131 if (status != WIFI_SUCCESS) {
Roshan Pius908a69a2016-10-03 13:33:23 -0700132 LOG(ERROR) << "Failed to initialize legacy hal function table";
133 return WIFI_ERROR_UNKNOWN;
134 }
135 if (!if_tool.SetWifiUpState(true)) {
136 LOG(ERROR) << "Failed to set WiFi interface up";
137 return WIFI_ERROR_UNKNOWN;
138 }
139
Roshan Piusaabe5752016-09-29 09:03:59 -0700140 LOG(INFO) << "Starting legacy HAL";
Roshan Pius955542e2016-10-28 09:42:44 -0700141 status = global_func_table_.wifi_initialize(&global_handle_);
Roshan Piusaabe5752016-09-29 09:03:59 -0700142 if (status != WIFI_SUCCESS || !global_handle_) {
143 LOG(ERROR) << "Failed to retrieve global handle";
144 return status;
145 }
146 event_loop_thread_ = std::thread(&WifiLegacyHal::runEventLoop, this);
147 status = retrieveWlanInterfaceHandle();
148 if (status != WIFI_SUCCESS || !wlan_interface_handle_) {
149 LOG(ERROR) << "Failed to retrieve wlan interface handle";
150 return status;
151 }
152 LOG(VERBOSE) << "Legacy HAL start complete";
153 return WIFI_SUCCESS;
154}
155
156wifi_error WifiLegacyHal::stop(
157 const std::function<void()>& on_stop_complete_user_callback) {
158 LOG(INFO) << "Stopping legacy HAL";
159 on_stop_complete_internal_callback = [&](wifi_handle handle) {
160 CHECK_EQ(global_handle_, handle) << "Handle mismatch";
161 on_stop_complete_user_callback();
Roshan Pius511cc492016-10-28 09:54:26 -0700162 // Invalidate all the internal pointers now that the HAL is
163 // stopped.
164 invalidate();
Roshan Piusaabe5752016-09-29 09:03:59 -0700165 };
166 awaiting_event_loop_termination_ = true;
167 global_func_table_.wifi_cleanup(global_handle_, onStopComplete);
168 LOG(VERBOSE) << "Legacy HAL stop initiated";
169 return WIFI_SUCCESS;
170}
171
Roshan Piusab5c4712016-10-06 14:37:15 -0700172std::string WifiLegacyHal::getApIfaceName() {
173 // Fake name. This interface does not exist in legacy HAL
174 // API's.
175 return "ap0";
176}
177
178std::string WifiLegacyHal::getNanIfaceName() {
179 // Fake name. This interface does not exist in legacy HAL
180 // API's.
181 return "nan0";
182}
183
184std::string WifiLegacyHal::getP2pIfaceName() {
185 std::array<char, PROPERTY_VALUE_MAX> buffer;
186 property_get("wifi.direct.interface", buffer.data(), "p2p0");
187 return buffer.data();
188}
189
190std::string WifiLegacyHal::getStaIfaceName() {
191 std::array<char, PROPERTY_VALUE_MAX> buffer;
192 property_get("wifi.interface", buffer.data(), "wlan0");
193 return buffer.data();
194}
195
196std::pair<wifi_error, std::string> WifiLegacyHal::getDriverVersion() {
Roshan Pius4b26c832016-10-03 12:49:58 -0700197 std::array<char, kMaxVersionStringLength> buffer;
198 buffer.fill(0);
199 wifi_error status = global_func_table_.wifi_get_driver_version(
200 wlan_interface_handle_, buffer.data(), buffer.size());
Roshan Pius0a47c182016-10-28 10:23:00 -0700201 return {status, buffer.data()};
Roshan Pius4b26c832016-10-03 12:49:58 -0700202}
203
Roshan Piusab5c4712016-10-06 14:37:15 -0700204std::pair<wifi_error, std::string> WifiLegacyHal::getFirmwareVersion() {
Roshan Pius4b26c832016-10-03 12:49:58 -0700205 std::array<char, kMaxVersionStringLength> buffer;
206 buffer.fill(0);
207 wifi_error status = global_func_table_.wifi_get_firmware_version(
208 wlan_interface_handle_, buffer.data(), buffer.size());
Roshan Pius0a47c182016-10-28 10:23:00 -0700209 return {status, buffer.data()};
Roshan Pius4b26c832016-10-03 12:49:58 -0700210}
211
Roshan Pius3c868522016-10-27 12:43:49 -0700212std::pair<wifi_error, std::vector<uint8_t>>
Roshan Piusab5c4712016-10-06 14:37:15 -0700213WifiLegacyHal::requestDriverMemoryDump() {
Roshan Pius3c868522016-10-27 12:43:49 -0700214 std::vector<uint8_t> driver_dump;
Roshan Piuscdb77f32016-10-03 14:09:57 -0700215 on_driver_memory_dump_internal_callback = [&driver_dump](char* buffer,
216 int buffer_size) {
Roshan Pius3c868522016-10-27 12:43:49 -0700217 driver_dump.insert(driver_dump.end(),
218 reinterpret_cast<uint8_t*>(buffer),
219 reinterpret_cast<uint8_t*>(buffer) + buffer_size);
Roshan Piuscdb77f32016-10-03 14:09:57 -0700220 };
221 wifi_error status = global_func_table_.wifi_get_driver_memory_dump(
222 wlan_interface_handle_, {onDriverMemoryDump});
223 on_driver_memory_dump_internal_callback = nullptr;
Roshan Pius0a47c182016-10-28 10:23:00 -0700224 return {status, std::move(driver_dump)};
Roshan Piuscdb77f32016-10-03 14:09:57 -0700225}
226
Roshan Pius3c868522016-10-27 12:43:49 -0700227std::pair<wifi_error, std::vector<uint8_t>>
Roshan Piusab5c4712016-10-06 14:37:15 -0700228WifiLegacyHal::requestFirmwareMemoryDump() {
Roshan Pius3c868522016-10-27 12:43:49 -0700229 std::vector<uint8_t> firmware_dump;
Roshan Piuscdb77f32016-10-03 14:09:57 -0700230 on_firmware_memory_dump_internal_callback = [&firmware_dump](
231 char* buffer, int buffer_size) {
Roshan Pius3c868522016-10-27 12:43:49 -0700232 firmware_dump.insert(firmware_dump.end(),
233 reinterpret_cast<uint8_t*>(buffer),
234 reinterpret_cast<uint8_t*>(buffer) + buffer_size);
Roshan Piuscdb77f32016-10-03 14:09:57 -0700235 };
236 wifi_error status = global_func_table_.wifi_get_firmware_memory_dump(
237 wlan_interface_handle_, {onFirmwareMemoryDump});
238 on_firmware_memory_dump_internal_callback = nullptr;
Roshan Pius0a47c182016-10-28 10:23:00 -0700239 return {status, std::move(firmware_dump)};
240}
241
242std::pair<wifi_error, uint32_t> WifiLegacyHal::getSupportedFeatureSet() {
243 feature_set set;
244 static_assert(sizeof(set) == sizeof(uint32_t),
245 "Some features can not be represented in output");
246 wifi_error status = global_func_table_.wifi_get_supported_feature_set(
247 wlan_interface_handle_, &set);
248 return {status, static_cast<uint32_t>(set)};
249}
250
251std::pair<wifi_error, PacketFilterCapabilities>
252WifiLegacyHal::getPacketFilterCapabilities() {
253 PacketFilterCapabilities caps;
254 wifi_error status = global_func_table_.wifi_get_packet_filter_capabilities(
255 wlan_interface_handle_, &caps.version, &caps.max_len);
256 return {status, caps};
257}
258
259wifi_error WifiLegacyHal::setPacketFilter(const std::vector<uint8_t>& program) {
260 return global_func_table_.wifi_set_packet_filter(
261 wlan_interface_handle_, program.data(), program.size());
Roshan Piuscdb77f32016-10-03 14:09:57 -0700262}
263
Roshan Pius76ff3022016-10-28 10:33:34 -0700264std::pair<wifi_error, wifi_gscan_capabilities>
265WifiLegacyHal::getGscanCapabilities() {
266 wifi_gscan_capabilities caps;
267 wifi_error status = global_func_table_.wifi_get_gscan_capabilities(
268 wlan_interface_handle_, &caps);
269 return {status, caps};
270}
271
272wifi_error WifiLegacyHal::startGscan(
273 wifi_request_id id,
274 const wifi_scan_cmd_params& params,
275 const std::function<void(wifi_request_id)>& on_failure_user_callback,
276 const on_gscan_results_callback& on_results_user_callback,
277 const on_gscan_full_result_callback& on_full_result_user_callback) {
278 // If there is already an ongoing background scan, reject new scan requests.
279 if (on_gscan_event_internal_callback ||
280 on_gscan_full_result_internal_callback) {
281 return WIFI_ERROR_NOT_AVAILABLE;
282 }
283
284 // This callback will be used to either trigger |on_results_user_callback| or
285 // |on_failure_user_callback|.
286 on_gscan_event_internal_callback =
287 [on_failure_user_callback, on_results_user_callback, this](
288 wifi_request_id id, wifi_scan_event event) {
289 switch (event) {
290 case WIFI_SCAN_RESULTS_AVAILABLE:
291 case WIFI_SCAN_THRESHOLD_NUM_SCANS:
292 case WIFI_SCAN_THRESHOLD_PERCENT: {
293 wifi_error status;
294 std::vector<wifi_cached_scan_results> cached_scan_results;
295 std::tie(status, cached_scan_results) = getGscanCachedResults();
296 if (status == WIFI_SUCCESS) {
297 on_results_user_callback(id, cached_scan_results);
298 return;
299 }
300 }
301 // Fall through if failed. Failure to retrieve cached scan results
302 // should trigger a background scan failure.
303 case WIFI_SCAN_FAILED:
304 on_failure_user_callback(id);
305 on_gscan_event_internal_callback = nullptr;
306 on_gscan_full_result_internal_callback = nullptr;
307 return;
308 }
309 LOG(FATAL) << "Unexpected gscan event received: " << event;
310 };
311
312 on_gscan_full_result_internal_callback = [on_full_result_user_callback](
313 wifi_request_id id, wifi_scan_result* result, uint32_t buckets_scanned) {
314 if (result) {
315 on_full_result_user_callback(id, result, buckets_scanned);
316 }
317 };
318
319 wifi_scan_result_handler handler = {onGscanFullResult, onGscanEvent};
320 wifi_error status = global_func_table_.wifi_start_gscan(
321 id, wlan_interface_handle_, params, handler);
322 if (status != WIFI_SUCCESS) {
323 on_gscan_event_internal_callback = nullptr;
324 on_gscan_full_result_internal_callback = nullptr;
325 }
326 return status;
327}
328
329wifi_error WifiLegacyHal::stopGscan(wifi_request_id id) {
330 // If there is no an ongoing background scan, reject stop requests.
331 // TODO(b/32337212): This needs to be handled by the HIDL object because we
332 // need to return the NOT_STARTED error code.
333 if (!on_gscan_event_internal_callback &&
334 !on_gscan_full_result_internal_callback) {
335 return WIFI_ERROR_NOT_AVAILABLE;
336 }
337 wifi_error status =
338 global_func_table_.wifi_stop_gscan(id, wlan_interface_handle_);
339 // If the request Id is wrong, don't stop the ongoing background scan. Any
340 // other error should be treated as the end of background scan.
341 if (status != WIFI_ERROR_INVALID_REQUEST_ID) {
342 on_gscan_event_internal_callback = nullptr;
343 on_gscan_full_result_internal_callback = nullptr;
344 }
345 return status;
346}
347
348std::pair<wifi_error, std::vector<uint32_t>>
349WifiLegacyHal::getValidFrequenciesForGscan(wifi_band band) {
350 static_assert(sizeof(uint32_t) >= sizeof(wifi_channel),
351 "Wifi Channel cannot be represented in output");
352 std::vector<uint32_t> freqs;
353 freqs.resize(kMaxGscanFrequenciesForBand);
354 int32_t num_freqs = 0;
355 wifi_error status = global_func_table_.wifi_get_valid_channels(
356 wlan_interface_handle_,
357 band,
358 freqs.size(),
359 reinterpret_cast<wifi_channel*>(freqs.data()),
360 &num_freqs);
361 CHECK(num_freqs >= 0 &&
362 static_cast<uint32_t>(num_freqs) <= kMaxGscanFrequenciesForBand);
363 freqs.resize(num_freqs);
364 return {status, std::move(freqs)};
365}
366
Roshan Pius7cece412016-10-28 10:38:21 -0700367wifi_error WifiLegacyHal::enableLinkLayerStats(bool debug) {
368 wifi_link_layer_params params;
369 params.mpdu_size_threshold = kLinkLayerStatsDataMpduSizeThreshold;
370 params.aggressive_statistics_gathering = debug;
371 return global_func_table_.wifi_set_link_stats(wlan_interface_handle_, params);
372}
373
374wifi_error WifiLegacyHal::disableLinkLayerStats() {
375 // TODO: Do we care about these responses?
376 uint32_t clear_mask_rsp;
377 uint8_t stop_rsp;
378 return global_func_table_.wifi_clear_link_stats(
379 wlan_interface_handle_, 0xFFFFFFFF, &clear_mask_rsp, 1, &stop_rsp);
380}
381
382std::pair<wifi_error, LinkLayerStats> WifiLegacyHal::getLinkLayerStats() {
383 LinkLayerStats link_stats{};
384 LinkLayerStats* link_stats_ptr = &link_stats;
385
386 on_link_layer_stats_result_internal_callback = [&link_stats_ptr](
387 wifi_request_id /* id */,
388 wifi_iface_stat* iface_stats_ptr,
389 int num_radios,
390 wifi_radio_stat* radio_stats_ptr) {
391 if (iface_stats_ptr != nullptr) {
392 link_stats_ptr->iface = *iface_stats_ptr;
393 link_stats_ptr->iface.num_peers = 0;
394 } else {
395 LOG(ERROR) << "Invalid iface stats in link layer stats";
396 }
397 if (num_radios == 1 && radio_stats_ptr != nullptr) {
398 link_stats_ptr->radio = *radio_stats_ptr;
399 // Copy over the tx level array to the separate vector.
400 if (radio_stats_ptr->num_tx_levels > 0 &&
401 radio_stats_ptr->tx_time_per_levels != nullptr) {
402 link_stats_ptr->radio_tx_time_per_levels.assign(
403 radio_stats_ptr->tx_time_per_levels,
404 radio_stats_ptr->tx_time_per_levels +
405 radio_stats_ptr->num_tx_levels);
406 }
407 link_stats_ptr->radio.num_tx_levels = 0;
408 link_stats_ptr->radio.tx_time_per_levels = nullptr;
409 } else {
410 LOG(ERROR) << "Invalid radio stats in link layer stats";
411 }
412 };
413
414 wifi_error status = global_func_table_.wifi_get_link_stats(
415 0, wlan_interface_handle_, {onLinkLayerStatsDataResult});
416 on_link_layer_stats_result_internal_callback = nullptr;
417 return {status, link_stats};
418}
419
Roshan Pius8714a3e2016-10-28 10:43:51 -0700420std::pair<wifi_error, uint32_t> WifiLegacyHal::getLoggerSupportedFeatureSet() {
421 uint32_t supported_features;
422 wifi_error status = global_func_table_.wifi_get_logger_supported_feature_set(
423 wlan_interface_handle_, &supported_features);
424 return {status, supported_features};
425}
426
427wifi_error WifiLegacyHal::startPktFateMonitoring() {
428 return global_func_table_.wifi_start_pkt_fate_monitoring(
429 wlan_interface_handle_);
430}
431
432std::pair<wifi_error, std::vector<wifi_tx_report>>
433WifiLegacyHal::getTxPktFates() {
434 std::vector<wifi_tx_report> tx_pkt_fates;
435 tx_pkt_fates.resize(MAX_FATE_LOG_LEN);
436 size_t num_fates = 0;
437 wifi_error status =
438 global_func_table_.wifi_get_tx_pkt_fates(wlan_interface_handle_,
439 tx_pkt_fates.data(),
440 tx_pkt_fates.size(),
441 &num_fates);
442 CHECK(num_fates <= MAX_FATE_LOG_LEN);
443 tx_pkt_fates.resize(num_fates);
444 return {status, std::move(tx_pkt_fates)};
445}
446
447std::pair<wifi_error, std::vector<wifi_rx_report>>
448WifiLegacyHal::getRxPktFates() {
449 std::vector<wifi_rx_report> rx_pkt_fates;
450 rx_pkt_fates.resize(MAX_FATE_LOG_LEN);
451 size_t num_fates = 0;
452 wifi_error status =
453 global_func_table_.wifi_get_rx_pkt_fates(wlan_interface_handle_,
454 rx_pkt_fates.data(),
455 rx_pkt_fates.size(),
456 &num_fates);
457 CHECK(num_fates <= MAX_FATE_LOG_LEN);
458 rx_pkt_fates.resize(num_fates);
459 return {status, std::move(rx_pkt_fates)};
460}
461
462std::pair<wifi_error, WakeReasonStats> WifiLegacyHal::getWakeReasonStats() {
463 WakeReasonStats stats;
464 stats.cmd_event_wake_cnt.resize(kMaxWakeReasonStatsArraySize);
465 stats.driver_fw_local_wake_cnt.resize(kMaxWakeReasonStatsArraySize);
466
467 // This legacy struct needs separate memory to store the variable sized wake
468 // reason types.
469 stats.wake_reason_cnt.cmd_event_wake_cnt =
470 reinterpret_cast<int32_t*>(stats.cmd_event_wake_cnt.data());
471 stats.wake_reason_cnt.cmd_event_wake_cnt_sz = stats.cmd_event_wake_cnt.size();
472 stats.wake_reason_cnt.cmd_event_wake_cnt_used = 0;
473 stats.wake_reason_cnt.driver_fw_local_wake_cnt =
474 reinterpret_cast<int32_t*>(stats.driver_fw_local_wake_cnt.data());
475 stats.wake_reason_cnt.driver_fw_local_wake_cnt_sz =
476 stats.driver_fw_local_wake_cnt.size();
477 stats.wake_reason_cnt.driver_fw_local_wake_cnt_used = 0;
478
479 wifi_error status = global_func_table_.wifi_get_wake_reason_stats(
480 wlan_interface_handle_, &stats.wake_reason_cnt);
481
482 CHECK(stats.wake_reason_cnt.cmd_event_wake_cnt_used >= 0 &&
483 static_cast<uint32_t>(stats.wake_reason_cnt.cmd_event_wake_cnt_used) <=
484 kMaxWakeReasonStatsArraySize);
485 stats.cmd_event_wake_cnt.resize(
486 stats.wake_reason_cnt.cmd_event_wake_cnt_used);
487 stats.wake_reason_cnt.cmd_event_wake_cnt = nullptr;
488
489 CHECK(stats.wake_reason_cnt.driver_fw_local_wake_cnt_used >= 0 &&
490 static_cast<uint32_t>(
491 stats.wake_reason_cnt.driver_fw_local_wake_cnt_used) <=
492 kMaxWakeReasonStatsArraySize);
493 stats.driver_fw_local_wake_cnt.resize(
494 stats.wake_reason_cnt.driver_fw_local_wake_cnt_used);
495 stats.wake_reason_cnt.driver_fw_local_wake_cnt = nullptr;
496
497 return {status, stats};
498}
499
500wifi_error WifiLegacyHal::registerRingBufferCallbackHandler(
501 const on_ring_buffer_data_callback& on_user_data_callback) {
502 if (on_ring_buffer_data_internal_callback) {
503 return WIFI_ERROR_NOT_AVAILABLE;
504 }
505 on_ring_buffer_data_internal_callback = [on_user_data_callback](
506 char* ring_name,
507 char* buffer,
508 int buffer_size,
509 wifi_ring_buffer_status* status) {
510 if (status && buffer) {
511 std::vector<uint8_t> buffer_vector(
512 reinterpret_cast<uint8_t*>(buffer),
513 reinterpret_cast<uint8_t*>(buffer) + buffer_size);
514 on_user_data_callback(ring_name, buffer_vector, *status);
515 }
516 };
517 return global_func_table_.wifi_set_log_handler(
518 0, wlan_interface_handle_, {onRingBufferData});
519}
520
521std::pair<wifi_error, std::vector<wifi_ring_buffer_status>>
522WifiLegacyHal::getRingBuffersStatus() {
523 std::vector<wifi_ring_buffer_status> ring_buffers_status;
524 ring_buffers_status.resize(kMaxRingBuffers);
525 uint32_t num_rings = 0;
526 wifi_error status = global_func_table_.wifi_get_ring_buffers_status(
527 wlan_interface_handle_, &num_rings, ring_buffers_status.data());
528 CHECK(num_rings <= kMaxRingBuffers);
529 ring_buffers_status.resize(num_rings);
530 return {status, std::move(ring_buffers_status)};
531}
532
533wifi_error WifiLegacyHal::startRingBufferLogging(const std::string& ring_name,
534 uint32_t verbose_level,
535 uint32_t max_interval_sec,
536 uint32_t min_data_size) {
537 std::vector<char> ring_name_internal(ring_name.begin(), ring_name.end());
538 return global_func_table_.wifi_start_logging(wlan_interface_handle_,
539 verbose_level,
540 0,
541 max_interval_sec,
542 min_data_size,
543 ring_name_internal.data());
544}
545
546wifi_error WifiLegacyHal::getRingBufferData(const std::string& ring_name) {
547 std::vector<char> ring_name_internal(ring_name.begin(), ring_name.end());
548 return global_func_table_.wifi_get_ring_data(wlan_interface_handle_,
549 ring_name_internal.data());
550}
551
Roshan Piusaabe5752016-09-29 09:03:59 -0700552wifi_error WifiLegacyHal::retrieveWlanInterfaceHandle() {
Roshan Piusab5c4712016-10-06 14:37:15 -0700553 const std::string& ifname_to_find = getStaIfaceName();
Roshan Piusaabe5752016-09-29 09:03:59 -0700554 wifi_interface_handle* iface_handles = nullptr;
555 int num_iface_handles = 0;
556 wifi_error status = global_func_table_.wifi_get_ifaces(
557 global_handle_, &num_iface_handles, &iface_handles);
558 if (status != WIFI_SUCCESS) {
Roshan Pius511cc492016-10-28 09:54:26 -0700559 LOG(ERROR) << "Failed to enumerate interface handles";
Roshan Piusaabe5752016-09-29 09:03:59 -0700560 return status;
561 }
562 for (int i = 0; i < num_iface_handles; ++i) {
563 std::array<char, IFNAMSIZ> current_ifname;
564 current_ifname.fill(0);
565 status = global_func_table_.wifi_get_iface_name(
566 iface_handles[i], current_ifname.data(), current_ifname.size());
567 if (status != WIFI_SUCCESS) {
Roshan Pius511cc492016-10-28 09:54:26 -0700568 LOG(WARNING) << "Failed to get interface handle name";
Roshan Piusaabe5752016-09-29 09:03:59 -0700569 continue;
570 }
571 if (ifname_to_find == current_ifname.data()) {
572 wlan_interface_handle_ = iface_handles[i];
573 return WIFI_SUCCESS;
574 }
575 }
576 return WIFI_ERROR_UNKNOWN;
577}
578
579void WifiLegacyHal::runEventLoop() {
580 LOG(VERBOSE) << "Starting legacy HAL event loop";
581 global_func_table_.wifi_event_loop(global_handle_);
582 if (!awaiting_event_loop_termination_) {
583 LOG(FATAL) << "Legacy HAL event loop terminated, but HAL was not stopping";
584 }
585 LOG(VERBOSE) << "Legacy HAL event loop terminated";
586 awaiting_event_loop_termination_ = false;
Roshan Pius908a69a2016-10-03 13:33:23 -0700587 android::wifi_system::InterfaceTool if_tool;
588 if_tool.SetWifiUpState(false);
Roshan Piusaabe5752016-09-29 09:03:59 -0700589}
590
Roshan Pius76ff3022016-10-28 10:33:34 -0700591std::pair<wifi_error, std::vector<wifi_cached_scan_results>>
592WifiLegacyHal::getGscanCachedResults() {
593 std::vector<wifi_cached_scan_results> cached_scan_results;
594 cached_scan_results.resize(kMaxCachedGscanResults);
595 int32_t num_results = 0;
596 wifi_error status = global_func_table_.wifi_get_cached_gscan_results(
597 wlan_interface_handle_,
598 true /* always flush */,
599 cached_scan_results.size(),
600 cached_scan_results.data(),
601 &num_results);
602 CHECK(num_results >= 0 &&
603 static_cast<uint32_t>(num_results) <= kMaxCachedGscanResults);
604 cached_scan_results.resize(num_results);
605 // Check for invalid IE lengths in these cached scan results and correct it.
606 for (auto& cached_scan_result : cached_scan_results) {
607 int num_scan_results = cached_scan_result.num_results;
608 for (int i = 0; i < num_scan_results; i++) {
609 auto& scan_result = cached_scan_result.results[i];
610 if (scan_result.ie_length > 0) {
611 LOG(ERROR) << "Cached scan result has non-zero IE length "
612 << scan_result.ie_length;
613 scan_result.ie_length = 0;
614 }
615 }
616 }
617 return {status, std::move(cached_scan_results)};
618}
619
Roshan Pius511cc492016-10-28 09:54:26 -0700620void WifiLegacyHal::invalidate() {
621 global_handle_ = nullptr;
622 wlan_interface_handle_ = nullptr;
623 on_stop_complete_internal_callback = nullptr;
624 on_driver_memory_dump_internal_callback = nullptr;
625 on_firmware_memory_dump_internal_callback = nullptr;
Roshan Pius76ff3022016-10-28 10:33:34 -0700626 on_gscan_event_internal_callback = nullptr;
627 on_gscan_full_result_internal_callback = nullptr;
Roshan Pius7cece412016-10-28 10:38:21 -0700628 on_link_layer_stats_result_internal_callback = nullptr;
Roshan Pius8714a3e2016-10-28 10:43:51 -0700629 on_ring_buffer_data_internal_callback = nullptr;
Roshan Pius511cc492016-10-28 09:54:26 -0700630}
Roshan Pius955542e2016-10-28 09:42:44 -0700631
632} // namespace legacy_hal
Roshan Piusaabe5752016-09-29 09:03:59 -0700633} // namespace implementation
634} // namespace V1_0
635} // namespace wifi
636} // namespace hardware
637} // namespace android