blob: 83f368e0bfc8975ac655691a2a899849ddc0980d [file] [log] [blame]
Gabriel Birenf3262f92022-07-15 23:25:39 +00001/*
2 * Copyright (C) 2022 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_legacy_hal.h"
18
19#include <android-base/logging.h>
20#include <cutils/properties.h>
21#include <net/if.h>
22
23#include <array>
24#include <chrono>
25
26#include "aidl_sync_util.h"
27#include "wifi_legacy_hal_stubs.h"
28
29namespace {
30// Constants ported over from the legacy HAL calling code
31// (com_android_server_wifi_WifiNative.cpp). This will all be thrown
32// away when this shim layer is replaced by the real vendor
33// implementation.
34static constexpr uint32_t kMaxVersionStringLength = 256;
35static constexpr uint32_t kMaxCachedGscanResults = 64;
36static constexpr uint32_t kMaxGscanFrequenciesForBand = 64;
37static constexpr uint32_t kLinkLayerStatsDataMpduSizeThreshold = 128;
38static constexpr uint32_t kMaxWakeReasonStatsArraySize = 32;
39static constexpr uint32_t kMaxRingBuffers = 10;
40static constexpr uint32_t kMaxWifiUsableChannels = 256;
41static constexpr uint32_t kMaxSupportedRadioCombinationsMatrixLength = 256;
42// Need a long timeout (1000ms) for chips that unload their driver.
43static constexpr uint32_t kMaxStopCompleteWaitMs = 1000;
44static constexpr char kDriverPropName[] = "wlan.driver.status";
45
46// Helper function to create a non-const char* for legacy Hal API's.
47std::vector<char> makeCharVec(const std::string& str) {
48 std::vector<char> vec(str.size() + 1);
49 vec.assign(str.begin(), str.end());
50 vec.push_back('\0');
51 return vec;
52}
53} // namespace
54
55namespace aidl {
56namespace android {
57namespace hardware {
58namespace wifi {
59namespace legacy_hal {
60
61// Legacy HAL functions accept "C" style function pointers, so use global
62// functions to pass to the legacy HAL function and store the corresponding
63// std::function methods to be invoked.
64//
65// Callback to be invoked once |stop| is complete
66std::function<void(wifi_handle handle)> on_stop_complete_internal_callback;
67void onAsyncStopComplete(wifi_handle handle) {
68 const auto lock = aidl_sync_util::acquireGlobalLock();
69 if (on_stop_complete_internal_callback) {
70 on_stop_complete_internal_callback(handle);
71 // Invalidate this callback since we don't want this firing again.
72 on_stop_complete_internal_callback = nullptr;
73 }
74}
75
76// Callback to be invoked for driver dump.
77std::function<void(char*, int)> on_driver_memory_dump_internal_callback;
78void onSyncDriverMemoryDump(char* buffer, int buffer_size) {
79 if (on_driver_memory_dump_internal_callback) {
80 on_driver_memory_dump_internal_callback(buffer, buffer_size);
81 }
82}
83
84// Callback to be invoked for firmware dump.
85std::function<void(char*, int)> on_firmware_memory_dump_internal_callback;
86void onSyncFirmwareMemoryDump(char* buffer, int buffer_size) {
87 if (on_firmware_memory_dump_internal_callback) {
88 on_firmware_memory_dump_internal_callback(buffer, buffer_size);
89 }
90}
91
92// Callback to be invoked for Gscan events.
93std::function<void(wifi_request_id, wifi_scan_event)> on_gscan_event_internal_callback;
94void onAsyncGscanEvent(wifi_request_id id, wifi_scan_event event) {
95 const auto lock = aidl_sync_util::acquireGlobalLock();
96 if (on_gscan_event_internal_callback) {
97 on_gscan_event_internal_callback(id, event);
98 }
99}
100
101// Callback to be invoked for Gscan full results.
102std::function<void(wifi_request_id, wifi_scan_result*, uint32_t)>
103 on_gscan_full_result_internal_callback;
104void onAsyncGscanFullResult(wifi_request_id id, wifi_scan_result* result,
105 uint32_t buckets_scanned) {
106 const auto lock = aidl_sync_util::acquireGlobalLock();
107 if (on_gscan_full_result_internal_callback) {
108 on_gscan_full_result_internal_callback(id, result, buckets_scanned);
109 }
110}
111
112// Callback to be invoked for link layer stats results.
113std::function<void((wifi_request_id, wifi_iface_stat*, int, wifi_radio_stat*))>
114 on_link_layer_stats_result_internal_callback;
115void onSyncLinkLayerStatsResult(wifi_request_id id, wifi_iface_stat* iface_stat, int num_radios,
116 wifi_radio_stat* radio_stat) {
117 if (on_link_layer_stats_result_internal_callback) {
118 on_link_layer_stats_result_internal_callback(id, iface_stat, num_radios, radio_stat);
119 }
120}
121
Mahesh KKV5f30d332022-10-26 14:07:44 -0700122// Callback to be invoked for Multi link layer stats results.
123std::function<void((wifi_request_id, wifi_iface_ml_stat*, int, wifi_radio_stat*))>
124 on_link_layer_ml_stats_result_internal_callback;
125void onSyncLinkLayerMlStatsResult(wifi_request_id id, wifi_iface_ml_stat* iface_ml_stat,
126 int num_radios, wifi_radio_stat* radio_stat) {
127 if (on_link_layer_ml_stats_result_internal_callback) {
128 on_link_layer_ml_stats_result_internal_callback(id, iface_ml_stat, num_radios, radio_stat);
129 }
130}
131
Gabriel Birenf3262f92022-07-15 23:25:39 +0000132// Callback to be invoked for rssi threshold breach.
133std::function<void((wifi_request_id, uint8_t*, int8_t))>
134 on_rssi_threshold_breached_internal_callback;
135void onAsyncRssiThresholdBreached(wifi_request_id id, uint8_t* bssid, int8_t rssi) {
136 const auto lock = aidl_sync_util::acquireGlobalLock();
137 if (on_rssi_threshold_breached_internal_callback) {
138 on_rssi_threshold_breached_internal_callback(id, bssid, rssi);
139 }
140}
141
142// Callback to be invoked for ring buffer data indication.
143std::function<void(char*, char*, int, wifi_ring_buffer_status*)>
144 on_ring_buffer_data_internal_callback;
145void onAsyncRingBufferData(char* ring_name, char* buffer, int buffer_size,
146 wifi_ring_buffer_status* status) {
147 const auto lock = aidl_sync_util::acquireGlobalLock();
148 if (on_ring_buffer_data_internal_callback) {
149 on_ring_buffer_data_internal_callback(ring_name, buffer, buffer_size, status);
150 }
151}
152
153// Callback to be invoked for error alert indication.
154std::function<void(wifi_request_id, char*, int, int)> on_error_alert_internal_callback;
155void onAsyncErrorAlert(wifi_request_id id, char* buffer, int buffer_size, int err_code) {
156 const auto lock = aidl_sync_util::acquireGlobalLock();
157 if (on_error_alert_internal_callback) {
158 on_error_alert_internal_callback(id, buffer, buffer_size, err_code);
159 }
160}
161
162// Callback to be invoked for radio mode change indication.
163std::function<void(wifi_request_id, uint32_t, wifi_mac_info*)>
164 on_radio_mode_change_internal_callback;
165void onAsyncRadioModeChange(wifi_request_id id, uint32_t num_macs, wifi_mac_info* mac_infos) {
166 const auto lock = aidl_sync_util::acquireGlobalLock();
167 if (on_radio_mode_change_internal_callback) {
168 on_radio_mode_change_internal_callback(id, num_macs, mac_infos);
169 }
170}
171
172// Callback to be invoked to report subsystem restart
173std::function<void(const char*)> on_subsystem_restart_internal_callback;
174void onAsyncSubsystemRestart(const char* error) {
175 const auto lock = aidl_sync_util::acquireGlobalLock();
176 if (on_subsystem_restart_internal_callback) {
177 on_subsystem_restart_internal_callback(error);
178 }
179}
180
181// Callback to be invoked for rtt results results.
182std::function<void(wifi_request_id, unsigned num_results, wifi_rtt_result* rtt_results[])>
183 on_rtt_results_internal_callback;
184void onAsyncRttResults(wifi_request_id id, unsigned num_results, wifi_rtt_result* rtt_results[]) {
185 const auto lock = aidl_sync_util::acquireGlobalLock();
186 if (on_rtt_results_internal_callback) {
187 on_rtt_results_internal_callback(id, num_results, rtt_results);
188 on_rtt_results_internal_callback = nullptr;
189 }
190}
191
192// Callbacks for the various NAN operations.
193// NOTE: These have very little conversions to perform before invoking the user
194// callbacks.
195// So, handle all of them here directly to avoid adding an unnecessary layer.
196std::function<void(transaction_id, const NanResponseMsg&)> on_nan_notify_response_user_callback;
197void onAsyncNanNotifyResponse(transaction_id id, NanResponseMsg* msg) {
198 const auto lock = aidl_sync_util::acquireGlobalLock();
199 if (on_nan_notify_response_user_callback && msg) {
200 on_nan_notify_response_user_callback(id, *msg);
201 }
202}
203
204std::function<void(const NanPublishRepliedInd&)> on_nan_event_publish_replied_user_callback;
205void onAsyncNanEventPublishReplied(NanPublishRepliedInd* /* event */) {
206 LOG(ERROR) << "onAsyncNanEventPublishReplied triggered";
207}
208
209std::function<void(const NanPublishTerminatedInd&)> on_nan_event_publish_terminated_user_callback;
210void onAsyncNanEventPublishTerminated(NanPublishTerminatedInd* event) {
211 const auto lock = aidl_sync_util::acquireGlobalLock();
212 if (on_nan_event_publish_terminated_user_callback && event) {
213 on_nan_event_publish_terminated_user_callback(*event);
214 }
215}
216
217std::function<void(const NanMatchInd&)> on_nan_event_match_user_callback;
218void onAsyncNanEventMatch(NanMatchInd* event) {
219 const auto lock = aidl_sync_util::acquireGlobalLock();
220 if (on_nan_event_match_user_callback && event) {
221 on_nan_event_match_user_callback(*event);
222 }
223}
224
225std::function<void(const NanMatchExpiredInd&)> on_nan_event_match_expired_user_callback;
226void onAsyncNanEventMatchExpired(NanMatchExpiredInd* event) {
227 const auto lock = aidl_sync_util::acquireGlobalLock();
228 if (on_nan_event_match_expired_user_callback && event) {
229 on_nan_event_match_expired_user_callback(*event);
230 }
231}
232
233std::function<void(const NanSubscribeTerminatedInd&)>
234 on_nan_event_subscribe_terminated_user_callback;
235void onAsyncNanEventSubscribeTerminated(NanSubscribeTerminatedInd* event) {
236 const auto lock = aidl_sync_util::acquireGlobalLock();
237 if (on_nan_event_subscribe_terminated_user_callback && event) {
238 on_nan_event_subscribe_terminated_user_callback(*event);
239 }
240}
241
242std::function<void(const NanFollowupInd&)> on_nan_event_followup_user_callback;
243void onAsyncNanEventFollowup(NanFollowupInd* event) {
244 const auto lock = aidl_sync_util::acquireGlobalLock();
245 if (on_nan_event_followup_user_callback && event) {
246 on_nan_event_followup_user_callback(*event);
247 }
248}
249
250std::function<void(const NanDiscEngEventInd&)> on_nan_event_disc_eng_event_user_callback;
251void onAsyncNanEventDiscEngEvent(NanDiscEngEventInd* event) {
252 const auto lock = aidl_sync_util::acquireGlobalLock();
253 if (on_nan_event_disc_eng_event_user_callback && event) {
254 on_nan_event_disc_eng_event_user_callback(*event);
255 }
256}
257
258std::function<void(const NanDisabledInd&)> on_nan_event_disabled_user_callback;
259void onAsyncNanEventDisabled(NanDisabledInd* event) {
260 const auto lock = aidl_sync_util::acquireGlobalLock();
261 if (on_nan_event_disabled_user_callback && event) {
262 on_nan_event_disabled_user_callback(*event);
263 }
264}
265
266std::function<void(const NanTCAInd&)> on_nan_event_tca_user_callback;
267void onAsyncNanEventTca(NanTCAInd* event) {
268 const auto lock = aidl_sync_util::acquireGlobalLock();
269 if (on_nan_event_tca_user_callback && event) {
270 on_nan_event_tca_user_callback(*event);
271 }
272}
273
274std::function<void(const NanBeaconSdfPayloadInd&)> on_nan_event_beacon_sdf_payload_user_callback;
275void onAsyncNanEventBeaconSdfPayload(NanBeaconSdfPayloadInd* event) {
276 const auto lock = aidl_sync_util::acquireGlobalLock();
277 if (on_nan_event_beacon_sdf_payload_user_callback && event) {
278 on_nan_event_beacon_sdf_payload_user_callback(*event);
279 }
280}
281
282std::function<void(const NanDataPathRequestInd&)> on_nan_event_data_path_request_user_callback;
283void onAsyncNanEventDataPathRequest(NanDataPathRequestInd* event) {
284 const auto lock = aidl_sync_util::acquireGlobalLock();
285 if (on_nan_event_data_path_request_user_callback && event) {
286 on_nan_event_data_path_request_user_callback(*event);
287 }
288}
289std::function<void(const NanDataPathConfirmInd&)> on_nan_event_data_path_confirm_user_callback;
290void onAsyncNanEventDataPathConfirm(NanDataPathConfirmInd* event) {
291 const auto lock = aidl_sync_util::acquireGlobalLock();
292 if (on_nan_event_data_path_confirm_user_callback && event) {
293 on_nan_event_data_path_confirm_user_callback(*event);
294 }
295}
296
297std::function<void(const NanDataPathEndInd&)> on_nan_event_data_path_end_user_callback;
298void onAsyncNanEventDataPathEnd(NanDataPathEndInd* event) {
299 const auto lock = aidl_sync_util::acquireGlobalLock();
300 if (on_nan_event_data_path_end_user_callback && event) {
301 on_nan_event_data_path_end_user_callback(*event);
302 }
303}
304
305std::function<void(const NanTransmitFollowupInd&)> on_nan_event_transmit_follow_up_user_callback;
306void onAsyncNanEventTransmitFollowUp(NanTransmitFollowupInd* event) {
307 const auto lock = aidl_sync_util::acquireGlobalLock();
308 if (on_nan_event_transmit_follow_up_user_callback && event) {
309 on_nan_event_transmit_follow_up_user_callback(*event);
310 }
311}
312
313std::function<void(const NanRangeRequestInd&)> on_nan_event_range_request_user_callback;
314void onAsyncNanEventRangeRequest(NanRangeRequestInd* event) {
315 const auto lock = aidl_sync_util::acquireGlobalLock();
316 if (on_nan_event_range_request_user_callback && event) {
317 on_nan_event_range_request_user_callback(*event);
318 }
319}
320
321std::function<void(const NanRangeReportInd&)> on_nan_event_range_report_user_callback;
322void onAsyncNanEventRangeReport(NanRangeReportInd* event) {
323 const auto lock = aidl_sync_util::acquireGlobalLock();
324 if (on_nan_event_range_report_user_callback && event) {
325 on_nan_event_range_report_user_callback(*event);
326 }
327}
328
329std::function<void(const NanDataPathScheduleUpdateInd&)> on_nan_event_schedule_update_user_callback;
330void onAsyncNanEventScheduleUpdate(NanDataPathScheduleUpdateInd* event) {
331 const auto lock = aidl_sync_util::acquireGlobalLock();
332 if (on_nan_event_schedule_update_user_callback && event) {
333 on_nan_event_schedule_update_user_callback(*event);
334 }
335}
336
337// Callbacks for the various TWT operations.
338std::function<void(const TwtSetupResponse&)> on_twt_event_setup_response_callback;
339void onAsyncTwtEventSetupResponse(TwtSetupResponse* event) {
340 const auto lock = aidl_sync_util::acquireGlobalLock();
341 if (on_twt_event_setup_response_callback && event) {
342 on_twt_event_setup_response_callback(*event);
343 }
344}
345
346std::function<void(const TwtTeardownCompletion&)> on_twt_event_teardown_completion_callback;
347void onAsyncTwtEventTeardownCompletion(TwtTeardownCompletion* event) {
348 const auto lock = aidl_sync_util::acquireGlobalLock();
349 if (on_twt_event_teardown_completion_callback && event) {
350 on_twt_event_teardown_completion_callback(*event);
351 }
352}
353
354std::function<void(const TwtInfoFrameReceived&)> on_twt_event_info_frame_received_callback;
355void onAsyncTwtEventInfoFrameReceived(TwtInfoFrameReceived* event) {
356 const auto lock = aidl_sync_util::acquireGlobalLock();
357 if (on_twt_event_info_frame_received_callback && event) {
358 on_twt_event_info_frame_received_callback(*event);
359 }
360}
361
362std::function<void(const TwtDeviceNotify&)> on_twt_event_device_notify_callback;
363void onAsyncTwtEventDeviceNotify(TwtDeviceNotify* event) {
364 const auto lock = aidl_sync_util::acquireGlobalLock();
365 if (on_twt_event_device_notify_callback && event) {
366 on_twt_event_device_notify_callback(*event);
367 }
368}
369
370// Callback to report current CHRE NAN state
371std::function<void(chre_nan_rtt_state)> on_chre_nan_rtt_internal_callback;
372void onAsyncChreNanRttState(chre_nan_rtt_state state) {
373 const auto lock = aidl_sync_util::acquireGlobalLock();
374 if (on_chre_nan_rtt_internal_callback) {
375 on_chre_nan_rtt_internal_callback(state);
376 }
377}
378
379// Callback to report cached scan results
380std::function<void(wifi_cached_scan_report*)> on_cached_scan_results_internal_callback;
381void onSyncCachedScanResults(wifi_cached_scan_report* cache_report) {
382 if (on_cached_scan_results_internal_callback) {
383 on_cached_scan_results_internal_callback(cache_report);
384 }
385}
386
387// End of the free-standing "C" style callbacks.
388
389WifiLegacyHal::WifiLegacyHal(const std::weak_ptr<::android::wifi_system::InterfaceTool> iface_tool,
390 const wifi_hal_fn& fn, bool is_primary)
391 : global_func_table_(fn),
392 global_handle_(nullptr),
393 awaiting_event_loop_termination_(false),
394 is_started_(false),
395 iface_tool_(iface_tool),
396 is_primary_(is_primary) {}
397
398wifi_error WifiLegacyHal::initialize() {
399 LOG(DEBUG) << "Initialize legacy HAL";
400 // this now does nothing, since HAL function table is provided
401 // to the constructor
402 return WIFI_SUCCESS;
403}
404
405wifi_error WifiLegacyHal::start() {
406 // Ensure that we're starting in a good state.
407 CHECK(global_func_table_.wifi_initialize && !global_handle_ && iface_name_to_handle_.empty() &&
408 !awaiting_event_loop_termination_);
409 if (is_started_) {
410 LOG(DEBUG) << "Legacy HAL already started";
411 return WIFI_SUCCESS;
412 }
413 LOG(DEBUG) << "Waiting for the driver ready";
414 wifi_error status = global_func_table_.wifi_wait_for_driver_ready();
415 if (status == WIFI_ERROR_TIMED_OUT || status == WIFI_ERROR_UNKNOWN) {
416 LOG(ERROR) << "Failed or timed out awaiting driver ready";
417 return status;
418 }
419
420 if (is_primary_) {
421 property_set(kDriverPropName, "ok");
422
423 if (!iface_tool_.lock()->SetWifiUpState(true)) {
424 LOG(ERROR) << "Failed to set WiFi interface up";
425 return WIFI_ERROR_UNKNOWN;
426 }
427 }
428
429 LOG(DEBUG) << "Starting legacy HAL";
430 status = global_func_table_.wifi_initialize(&global_handle_);
431 if (status != WIFI_SUCCESS || !global_handle_) {
432 LOG(ERROR) << "Failed to retrieve global handle";
433 return status;
434 }
435 std::thread(&WifiLegacyHal::runEventLoop, this).detach();
436 status = retrieveIfaceHandles();
437 if (status != WIFI_SUCCESS || iface_name_to_handle_.empty()) {
438 LOG(ERROR) << "Failed to retrieve wlan interface handle";
439 return status;
440 }
441 LOG(DEBUG) << "Legacy HAL start complete";
442 is_started_ = true;
443 return WIFI_SUCCESS;
444}
445
446wifi_error WifiLegacyHal::stop(
447 /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,
448 const std::function<void()>& on_stop_complete_user_callback) {
449 if (!is_started_) {
450 LOG(DEBUG) << "Legacy HAL already stopped";
451 on_stop_complete_user_callback();
452 return WIFI_SUCCESS;
453 }
454 LOG(DEBUG) << "Stopping legacy HAL";
455 on_stop_complete_internal_callback = [on_stop_complete_user_callback,
456 this](wifi_handle handle) {
457 CHECK_EQ(global_handle_, handle) << "Handle mismatch";
458 LOG(INFO) << "Legacy HAL stop complete callback received";
459 // Invalidate all the internal pointers now that the HAL is
460 // stopped.
461 invalidate();
462 if (is_primary_) iface_tool_.lock()->SetWifiUpState(false);
463 on_stop_complete_user_callback();
464 is_started_ = false;
465 };
466 awaiting_event_loop_termination_ = true;
467 global_func_table_.wifi_cleanup(global_handle_, onAsyncStopComplete);
468 const auto status =
469 stop_wait_cv_.wait_for(*lock, std::chrono::milliseconds(kMaxStopCompleteWaitMs),
470 [this] { return !awaiting_event_loop_termination_; });
471 if (!status) {
472 LOG(ERROR) << "Legacy HAL stop failed or timed out";
473 return WIFI_ERROR_UNKNOWN;
474 }
475 LOG(DEBUG) << "Legacy HAL stop complete";
476 return WIFI_SUCCESS;
477}
478
479bool WifiLegacyHal::isStarted() {
480 return is_started_;
481}
482
483wifi_error WifiLegacyHal::waitForDriverReady() {
484 return global_func_table_.wifi_wait_for_driver_ready();
485}
486
487std::pair<wifi_error, std::string> WifiLegacyHal::getDriverVersion(const std::string& iface_name) {
488 std::array<char, kMaxVersionStringLength> buffer;
489 buffer.fill(0);
490 wifi_error status = global_func_table_.wifi_get_driver_version(getIfaceHandle(iface_name),
491 buffer.data(), buffer.size());
492 return {status, buffer.data()};
493}
494
495std::pair<wifi_error, std::string> WifiLegacyHal::getFirmwareVersion(
496 const std::string& iface_name) {
497 std::array<char, kMaxVersionStringLength> buffer;
498 buffer.fill(0);
499 wifi_error status = global_func_table_.wifi_get_firmware_version(getIfaceHandle(iface_name),
500 buffer.data(), buffer.size());
501 return {status, buffer.data()};
502}
503
504std::pair<wifi_error, std::vector<uint8_t>> WifiLegacyHal::requestDriverMemoryDump(
505 const std::string& iface_name) {
506 std::vector<uint8_t> driver_dump;
507 on_driver_memory_dump_internal_callback = [&driver_dump](char* buffer, int buffer_size) {
508 driver_dump.insert(driver_dump.end(), reinterpret_cast<uint8_t*>(buffer),
509 reinterpret_cast<uint8_t*>(buffer) + buffer_size);
510 };
511 wifi_error status = global_func_table_.wifi_get_driver_memory_dump(getIfaceHandle(iface_name),
512 {onSyncDriverMemoryDump});
513 on_driver_memory_dump_internal_callback = nullptr;
514 return {status, std::move(driver_dump)};
515}
516
517std::pair<wifi_error, std::vector<uint8_t>> WifiLegacyHal::requestFirmwareMemoryDump(
518 const std::string& iface_name) {
519 std::vector<uint8_t> firmware_dump;
520 on_firmware_memory_dump_internal_callback = [&firmware_dump](char* buffer, int buffer_size) {
521 firmware_dump.insert(firmware_dump.end(), reinterpret_cast<uint8_t*>(buffer),
522 reinterpret_cast<uint8_t*>(buffer) + buffer_size);
523 };
524 wifi_error status = global_func_table_.wifi_get_firmware_memory_dump(
525 getIfaceHandle(iface_name), {onSyncFirmwareMemoryDump});
526 on_firmware_memory_dump_internal_callback = nullptr;
527 return {status, std::move(firmware_dump)};
528}
529
530std::pair<wifi_error, uint64_t> WifiLegacyHal::getSupportedFeatureSet(
531 const std::string& iface_name) {
532 feature_set set = 0, chip_set = 0;
533 wifi_error status = WIFI_SUCCESS;
534
535 static_assert(sizeof(set) == sizeof(uint64_t),
536 "Some feature_flags can not be represented in output");
537 wifi_interface_handle iface_handle = getIfaceHandle(iface_name);
538
539 global_func_table_.wifi_get_chip_feature_set(
540 global_handle_, &chip_set); /* ignore error, chip_set will stay 0 */
541
542 if (iface_handle) {
543 status = global_func_table_.wifi_get_supported_feature_set(iface_handle, &set);
544 }
545 return {status, static_cast<uint64_t>(set | chip_set)};
546}
547
548std::pair<wifi_error, PacketFilterCapabilities> WifiLegacyHal::getPacketFilterCapabilities(
549 const std::string& iface_name) {
550 PacketFilterCapabilities caps;
551 wifi_error status = global_func_table_.wifi_get_packet_filter_capabilities(
552 getIfaceHandle(iface_name), &caps.version, &caps.max_len);
553 return {status, caps};
554}
555
556wifi_error WifiLegacyHal::setPacketFilter(const std::string& iface_name,
557 const std::vector<uint8_t>& program) {
558 return global_func_table_.wifi_set_packet_filter(getIfaceHandle(iface_name), program.data(),
559 program.size());
560}
561
562std::pair<wifi_error, std::vector<uint8_t>> WifiLegacyHal::readApfPacketFilterData(
563 const std::string& iface_name) {
564 PacketFilterCapabilities caps;
565 wifi_error status = global_func_table_.wifi_get_packet_filter_capabilities(
566 getIfaceHandle(iface_name), &caps.version, &caps.max_len);
567 if (status != WIFI_SUCCESS) {
568 return {status, {}};
569 }
570
571 // Size the buffer to read the entire program & work memory.
572 std::vector<uint8_t> buffer(caps.max_len);
573
574 status = global_func_table_.wifi_read_packet_filter(
575 getIfaceHandle(iface_name), /*src_offset=*/0, buffer.data(), buffer.size());
576 return {status, std::move(buffer)};
577}
578
579std::pair<wifi_error, wifi_gscan_capabilities> WifiLegacyHal::getGscanCapabilities(
580 const std::string& iface_name) {
581 wifi_gscan_capabilities caps;
582 wifi_error status =
583 global_func_table_.wifi_get_gscan_capabilities(getIfaceHandle(iface_name), &caps);
584 return {status, caps};
585}
586
587wifi_error WifiLegacyHal::startGscan(
588 const std::string& iface_name, wifi_request_id id, const wifi_scan_cmd_params& params,
589 const std::function<void(wifi_request_id)>& on_failure_user_callback,
590 const on_gscan_results_callback& on_results_user_callback,
591 const on_gscan_full_result_callback& on_full_result_user_callback) {
592 // If there is already an ongoing background scan, reject new scan requests.
593 if (on_gscan_event_internal_callback || on_gscan_full_result_internal_callback) {
594 return WIFI_ERROR_NOT_AVAILABLE;
595 }
596
597 // This callback will be used to either trigger |on_results_user_callback|
598 // or |on_failure_user_callback|.
599 on_gscan_event_internal_callback = [iface_name, on_failure_user_callback,
600 on_results_user_callback,
601 this](wifi_request_id id, wifi_scan_event event) {
602 switch (event) {
603 case WIFI_SCAN_RESULTS_AVAILABLE:
604 case WIFI_SCAN_THRESHOLD_NUM_SCANS:
605 case WIFI_SCAN_THRESHOLD_PERCENT: {
606 wifi_error status;
607 std::vector<wifi_cached_scan_results> cached_scan_results;
608 std::tie(status, cached_scan_results) = getGscanCachedResults(iface_name);
609 if (status == WIFI_SUCCESS) {
610 on_results_user_callback(id, cached_scan_results);
611 return;
612 }
613 FALLTHROUGH_INTENDED;
614 }
615 // Fall through if failed. Failure to retrieve cached scan
616 // results should trigger a background scan failure.
617 case WIFI_SCAN_FAILED:
618 on_failure_user_callback(id);
619 on_gscan_event_internal_callback = nullptr;
620 on_gscan_full_result_internal_callback = nullptr;
621 return;
622 }
623 LOG(FATAL) << "Unexpected gscan event received: " << event;
624 };
625
626 on_gscan_full_result_internal_callback = [on_full_result_user_callback](
627 wifi_request_id id, wifi_scan_result* result,
628 uint32_t buckets_scanned) {
629 if (result) {
630 on_full_result_user_callback(id, result, buckets_scanned);
631 }
632 };
633
634 wifi_scan_result_handler handler = {onAsyncGscanFullResult, onAsyncGscanEvent};
635 wifi_error status =
636 global_func_table_.wifi_start_gscan(id, getIfaceHandle(iface_name), params, handler);
637 if (status != WIFI_SUCCESS) {
638 on_gscan_event_internal_callback = nullptr;
639 on_gscan_full_result_internal_callback = nullptr;
640 }
641 return status;
642}
643
644wifi_error WifiLegacyHal::stopGscan(const std::string& iface_name, wifi_request_id id) {
645 // If there is no an ongoing background scan, reject stop requests.
646 // TODO(b/32337212): This needs to be handled by the HIDL object because we
647 // need to return the NOT_STARTED error code.
648 if (!on_gscan_event_internal_callback && !on_gscan_full_result_internal_callback) {
649 return WIFI_ERROR_NOT_AVAILABLE;
650 }
651 wifi_error status = global_func_table_.wifi_stop_gscan(id, getIfaceHandle(iface_name));
652 // If the request Id is wrong, don't stop the ongoing background scan. Any
653 // other error should be treated as the end of background scan.
654 if (status != WIFI_ERROR_INVALID_REQUEST_ID) {
655 on_gscan_event_internal_callback = nullptr;
656 on_gscan_full_result_internal_callback = nullptr;
657 }
658 return status;
659}
660
661std::pair<wifi_error, std::vector<uint32_t>> WifiLegacyHal::getValidFrequenciesForBand(
662 const std::string& iface_name, wifi_band band) {
663 static_assert(sizeof(uint32_t) >= sizeof(wifi_channel),
664 "Wifi Channel cannot be represented in output");
665 std::vector<uint32_t> freqs;
666 freqs.resize(kMaxGscanFrequenciesForBand);
667 int32_t num_freqs = 0;
668 wifi_error status = global_func_table_.wifi_get_valid_channels(
669 getIfaceHandle(iface_name), band, freqs.size(),
670 reinterpret_cast<wifi_channel*>(freqs.data()), &num_freqs);
671 CHECK(num_freqs >= 0 && static_cast<uint32_t>(num_freqs) <= kMaxGscanFrequenciesForBand);
672 freqs.resize(num_freqs);
673 return {status, std::move(freqs)};
674}
675
676wifi_error WifiLegacyHal::setDfsFlag(const std::string& iface_name, bool dfs_on) {
677 return global_func_table_.wifi_set_nodfs_flag(getIfaceHandle(iface_name), dfs_on ? 0 : 1);
678}
679
680wifi_error WifiLegacyHal::enableLinkLayerStats(const std::string& iface_name, bool debug) {
681 wifi_link_layer_params params;
682 params.mpdu_size_threshold = kLinkLayerStatsDataMpduSizeThreshold;
683 params.aggressive_statistics_gathering = debug;
684 return global_func_table_.wifi_set_link_stats(getIfaceHandle(iface_name), params);
685}
686
687wifi_error WifiLegacyHal::disableLinkLayerStats(const std::string& iface_name) {
688 // TODO: Do we care about these responses?
689 uint32_t clear_mask_rsp;
690 uint8_t stop_rsp;
691 return global_func_table_.wifi_clear_link_stats(getIfaceHandle(iface_name), 0xFFFFFFFF,
692 &clear_mask_rsp, 1, &stop_rsp);
693}
694
Mahesh KKV5f30d332022-10-26 14:07:44 -0700695// Copies wifi_peer_info* to vector<WifiPeerInfo> and returns poiner to next element.
696wifi_peer_info* WifiLegacyHal::copyPeerInfo(wifi_peer_info* peer_ptr,
697 std::vector<WifiPeerInfo> peers) {
698 WifiPeerInfo peer;
699 peer.peer_info = *peer_ptr;
700 if (peer_ptr->num_rate > 0) {
701 // Copy the rate stats.
702 peer.rate_stats.assign(peer_ptr->rate_stats, peer_ptr->rate_stats + peer_ptr->num_rate);
703 }
704 peer.peer_info.num_rate = 0;
705 // Push peer info.
706 peers.push_back(peer);
707 // Return the address of next peer info.
708 return (wifi_peer_info*)((u8*)peer_ptr + sizeof(wifi_peer_info) +
709 (sizeof(wifi_rate_stat) * peer_ptr->num_rate));
710}
711// Copies wifi_link_stat* to vector<LinkStats> and returns poiner to next element.
712wifi_link_stat* WifiLegacyHal::copyLinkStat(wifi_link_stat* stat_ptr,
713 std::vector<LinkStats> stats) {
714 LinkStats linkStat;
715 linkStat.stat = *stat_ptr;
716 wifi_peer_info* l_peer_info_stats_ptr = stat_ptr->peer_info;
717 for (uint32_t i = 0; i < linkStat.stat.num_peers; i++) {
718 l_peer_info_stats_ptr = copyPeerInfo(l_peer_info_stats_ptr, linkStat.peers);
719 }
720 // Copied all peers to linkStat.peers.
721 linkStat.stat.num_peers = 0;
722 // Push link stat.
723 stats.push_back(linkStat);
724 // Read all peers, return the address of next wifi_link_stat.
725 return (wifi_link_stat*)l_peer_info_stats_ptr;
726}
727
728wifi_error WifiLegacyHal::getLinkLayerStats(const std::string& iface_name,
729 LinkLayerStats& link_stats,
730 LinkLayerMlStats& link_ml_stats) {
Gabriel Birenf3262f92022-07-15 23:25:39 +0000731 LinkLayerStats* link_stats_ptr = &link_stats;
Mahesh KKV5f30d332022-10-26 14:07:44 -0700732 link_stats_ptr->valid = false;
Gabriel Birenf3262f92022-07-15 23:25:39 +0000733
734 on_link_layer_stats_result_internal_callback = [&link_stats_ptr](
735 wifi_request_id /* id */,
736 wifi_iface_stat* iface_stats_ptr,
737 int num_radios,
738 wifi_radio_stat* radio_stats_ptr) {
739 wifi_radio_stat* l_radio_stats_ptr;
740 wifi_peer_info* l_peer_info_stats_ptr;
Mahesh KKV5f30d332022-10-26 14:07:44 -0700741 link_stats_ptr->valid = true;
Gabriel Birenf3262f92022-07-15 23:25:39 +0000742
743 if (iface_stats_ptr != nullptr) {
744 link_stats_ptr->iface = *iface_stats_ptr;
745 l_peer_info_stats_ptr = iface_stats_ptr->peer_info;
746 for (uint32_t i = 0; i < iface_stats_ptr->num_peers; i++) {
747 WifiPeerInfo peer;
748 peer.peer_info = *l_peer_info_stats_ptr;
749 if (l_peer_info_stats_ptr->num_rate > 0) {
750 /* Copy the rate stats */
751 peer.rate_stats.assign(
752 l_peer_info_stats_ptr->rate_stats,
753 l_peer_info_stats_ptr->rate_stats + l_peer_info_stats_ptr->num_rate);
754 }
755 peer.peer_info.num_rate = 0;
756 link_stats_ptr->peers.push_back(peer);
757 l_peer_info_stats_ptr =
758 (wifi_peer_info*)((u8*)l_peer_info_stats_ptr + sizeof(wifi_peer_info) +
759 (sizeof(wifi_rate_stat) *
760 l_peer_info_stats_ptr->num_rate));
761 }
762 link_stats_ptr->iface.num_peers = 0;
763 } else {
764 LOG(ERROR) << "Invalid iface stats in link layer stats";
765 }
766 if (num_radios <= 0 || radio_stats_ptr == nullptr) {
767 LOG(ERROR) << "Invalid radio stats in link layer stats";
768 return;
769 }
770 l_radio_stats_ptr = radio_stats_ptr;
771 for (int i = 0; i < num_radios; i++) {
772 LinkLayerRadioStats radio;
773
774 radio.stats = *l_radio_stats_ptr;
775 // Copy over the tx level array to the separate vector.
776 if (l_radio_stats_ptr->num_tx_levels > 0 &&
777 l_radio_stats_ptr->tx_time_per_levels != nullptr) {
778 radio.tx_time_per_levels.assign(
779 l_radio_stats_ptr->tx_time_per_levels,
780 l_radio_stats_ptr->tx_time_per_levels + l_radio_stats_ptr->num_tx_levels);
781 }
782 radio.stats.num_tx_levels = 0;
783 radio.stats.tx_time_per_levels = nullptr;
784 /* Copy over the channel stat to separate vector */
785 if (l_radio_stats_ptr->num_channels > 0) {
786 /* Copy the channel stats */
787 radio.channel_stats.assign(
788 l_radio_stats_ptr->channels,
789 l_radio_stats_ptr->channels + l_radio_stats_ptr->num_channels);
790 }
791 link_stats_ptr->radios.push_back(radio);
792 l_radio_stats_ptr =
793 (wifi_radio_stat*)((u8*)l_radio_stats_ptr + sizeof(wifi_radio_stat) +
794 (sizeof(wifi_channel_stat) *
795 l_radio_stats_ptr->num_channels));
796 }
797 };
798
Mahesh KKV5f30d332022-10-26 14:07:44 -0700799 LinkLayerMlStats* link_ml_stats_ptr = &link_ml_stats;
800 link_ml_stats_ptr->valid = false;
801
802 on_link_layer_ml_stats_result_internal_callback =
803 [this, &link_ml_stats_ptr](wifi_request_id /* id */,
804 wifi_iface_ml_stat* iface_ml_stats_ptr, int num_radios,
805 wifi_radio_stat* radio_stats_ptr) {
806 wifi_radio_stat* l_radio_stats_ptr;
807 wifi_link_stat* l_link_stat_ptr;
808 link_ml_stats_ptr->valid = true;
809
810 if (iface_ml_stats_ptr != nullptr && iface_ml_stats_ptr->num_links > 0) {
811 // Copy stats from wifi_iface_ml_stat to LinkLayerMlStats,
812 // - num_links * links[] to vector of links.
813 // - num_peers * peer_info[] to vector of links[i].peers.
814 link_ml_stats_ptr->iface = *iface_ml_stats_ptr;
815 l_link_stat_ptr = iface_ml_stats_ptr->links;
816 for (int l = 0; l < iface_ml_stats_ptr->num_links; ++l) {
817 l_link_stat_ptr = copyLinkStat(l_link_stat_ptr, link_ml_stats_ptr->links);
818 }
819 } else {
820 LOG(ERROR) << "Invalid iface stats in link layer stats";
821 }
822 if (num_radios <= 0 || radio_stats_ptr == nullptr) {
823 LOG(ERROR) << "Invalid radio stats in link layer stats";
824 return;
825 }
826 l_radio_stats_ptr = radio_stats_ptr;
827 for (int i = 0; i < num_radios; i++) {
828 LinkLayerRadioStats radio;
829
830 radio.stats = *l_radio_stats_ptr;
831 // Copy over the tx level array to the separate vector.
832 if (l_radio_stats_ptr->num_tx_levels > 0 &&
833 l_radio_stats_ptr->tx_time_per_levels != nullptr) {
834 radio.tx_time_per_levels.assign(l_radio_stats_ptr->tx_time_per_levels,
835 l_radio_stats_ptr->tx_time_per_levels +
836 l_radio_stats_ptr->num_tx_levels);
837 }
838 radio.stats.num_tx_levels = 0;
839 radio.stats.tx_time_per_levels = nullptr;
840 /* Copy over the channel stat to separate vector */
841 if (l_radio_stats_ptr->num_channels > 0) {
842 /* Copy the channel stats */
843 radio.channel_stats.assign(
844 l_radio_stats_ptr->channels,
845 l_radio_stats_ptr->channels + l_radio_stats_ptr->num_channels);
846 }
847 link_ml_stats_ptr->radios.push_back(radio);
848 l_radio_stats_ptr =
849 (wifi_radio_stat*)((u8*)l_radio_stats_ptr + sizeof(wifi_radio_stat) +
850 (sizeof(wifi_channel_stat) *
851 l_radio_stats_ptr->num_channels));
852 }
853 };
854
855 wifi_error status = global_func_table_.wifi_get_link_stats(
856 0, getIfaceHandle(iface_name),
857 {onSyncLinkLayerStatsResult, onSyncLinkLayerMlStatsResult});
Gabriel Birenf3262f92022-07-15 23:25:39 +0000858 on_link_layer_stats_result_internal_callback = nullptr;
Mahesh KKV5f30d332022-10-26 14:07:44 -0700859 on_link_layer_ml_stats_result_internal_callback = nullptr;
860
861 return status;
Gabriel Birenf3262f92022-07-15 23:25:39 +0000862}
863
864wifi_error WifiLegacyHal::startRssiMonitoring(
865 const std::string& iface_name, wifi_request_id id, int8_t max_rssi, int8_t min_rssi,
866 const on_rssi_threshold_breached_callback& on_threshold_breached_user_callback) {
867 if (on_rssi_threshold_breached_internal_callback) {
868 return WIFI_ERROR_NOT_AVAILABLE;
869 }
870 on_rssi_threshold_breached_internal_callback = [on_threshold_breached_user_callback](
871 wifi_request_id id, uint8_t* bssid_ptr,
872 int8_t rssi) {
873 if (!bssid_ptr) {
874 return;
875 }
876 std::array<uint8_t, ETH_ALEN> bssid_arr;
877 // |bssid_ptr| pointer is assumed to have 6 bytes for the mac
878 // address.
879 std::copy(bssid_ptr, bssid_ptr + 6, std::begin(bssid_arr));
880 on_threshold_breached_user_callback(id, bssid_arr, rssi);
881 };
882 wifi_error status = global_func_table_.wifi_start_rssi_monitoring(
883 id, getIfaceHandle(iface_name), max_rssi, min_rssi, {onAsyncRssiThresholdBreached});
884 if (status != WIFI_SUCCESS) {
885 on_rssi_threshold_breached_internal_callback = nullptr;
886 }
887 return status;
888}
889
890wifi_error WifiLegacyHal::stopRssiMonitoring(const std::string& iface_name, wifi_request_id id) {
891 if (!on_rssi_threshold_breached_internal_callback) {
892 return WIFI_ERROR_NOT_AVAILABLE;
893 }
894 wifi_error status =
895 global_func_table_.wifi_stop_rssi_monitoring(id, getIfaceHandle(iface_name));
896 // If the request Id is wrong, don't stop the ongoing rssi monitoring. Any
897 // other error should be treated as the end of background scan.
898 if (status != WIFI_ERROR_INVALID_REQUEST_ID) {
899 on_rssi_threshold_breached_internal_callback = nullptr;
900 }
901 return status;
902}
903
904std::pair<wifi_error, wifi_roaming_capabilities> WifiLegacyHal::getRoamingCapabilities(
905 const std::string& iface_name) {
906 wifi_roaming_capabilities caps;
907 wifi_error status =
908 global_func_table_.wifi_get_roaming_capabilities(getIfaceHandle(iface_name), &caps);
909 return {status, caps};
910}
911
912wifi_error WifiLegacyHal::configureRoaming(const std::string& iface_name,
913 const wifi_roaming_config& config) {
914 wifi_roaming_config config_internal = config;
915 return global_func_table_.wifi_configure_roaming(getIfaceHandle(iface_name), &config_internal);
916}
917
918wifi_error WifiLegacyHal::enableFirmwareRoaming(const std::string& iface_name,
919 fw_roaming_state_t state) {
920 return global_func_table_.wifi_enable_firmware_roaming(getIfaceHandle(iface_name), state);
921}
922
923wifi_error WifiLegacyHal::configureNdOffload(const std::string& iface_name, bool enable) {
924 return global_func_table_.wifi_configure_nd_offload(getIfaceHandle(iface_name), enable);
925}
926
927wifi_error WifiLegacyHal::startSendingOffloadedPacket(const std::string& iface_name, int32_t cmd_id,
928 uint16_t ether_type,
929 const std::vector<uint8_t>& ip_packet_data,
930 const std::array<uint8_t, 6>& src_address,
931 const std::array<uint8_t, 6>& dst_address,
932 int32_t period_in_ms) {
933 std::vector<uint8_t> ip_packet_data_internal(ip_packet_data);
934 std::vector<uint8_t> src_address_internal(src_address.data(),
935 src_address.data() + src_address.size());
936 std::vector<uint8_t> dst_address_internal(dst_address.data(),
937 dst_address.data() + dst_address.size());
938 return global_func_table_.wifi_start_sending_offloaded_packet(
939 cmd_id, getIfaceHandle(iface_name), ether_type, ip_packet_data_internal.data(),
940 ip_packet_data_internal.size(), src_address_internal.data(),
941 dst_address_internal.data(), period_in_ms);
942}
943
944wifi_error WifiLegacyHal::stopSendingOffloadedPacket(const std::string& iface_name,
945 uint32_t cmd_id) {
946 return global_func_table_.wifi_stop_sending_offloaded_packet(cmd_id,
947 getIfaceHandle(iface_name));
948}
949
950wifi_error WifiLegacyHal::selectTxPowerScenario(const std::string& iface_name,
951 wifi_power_scenario scenario) {
952 return global_func_table_.wifi_select_tx_power_scenario(getIfaceHandle(iface_name), scenario);
953}
954
955wifi_error WifiLegacyHal::resetTxPowerScenario(const std::string& iface_name) {
956 return global_func_table_.wifi_reset_tx_power_scenario(getIfaceHandle(iface_name));
957}
958
959wifi_error WifiLegacyHal::setLatencyMode(const std::string& iface_name, wifi_latency_mode mode) {
960 return global_func_table_.wifi_set_latency_mode(getIfaceHandle(iface_name), mode);
961}
962
963wifi_error WifiLegacyHal::setThermalMitigationMode(wifi_thermal_mode mode,
964 uint32_t completion_window) {
965 return global_func_table_.wifi_set_thermal_mitigation_mode(global_handle_, mode,
966 completion_window);
967}
968
969wifi_error WifiLegacyHal::setDscpToAccessCategoryMapping(uint32_t start, uint32_t end,
970 uint32_t access_category) {
971 return global_func_table_.wifi_map_dscp_access_category(global_handle_, start, end,
972 access_category);
973}
974
975wifi_error WifiLegacyHal::resetDscpToAccessCategoryMapping() {
976 return global_func_table_.wifi_reset_dscp_mapping(global_handle_);
977}
978
979std::pair<wifi_error, uint32_t> WifiLegacyHal::getLoggerSupportedFeatureSet(
980 const std::string& iface_name) {
981 uint32_t supported_feature_flags = 0;
982 wifi_error status = WIFI_SUCCESS;
983
984 wifi_interface_handle iface_handle = getIfaceHandle(iface_name);
985
986 if (iface_handle) {
987 status = global_func_table_.wifi_get_logger_supported_feature_set(iface_handle,
988 &supported_feature_flags);
989 }
990 return {status, supported_feature_flags};
991}
992
993wifi_error WifiLegacyHal::startPktFateMonitoring(const std::string& iface_name) {
994 return global_func_table_.wifi_start_pkt_fate_monitoring(getIfaceHandle(iface_name));
995}
996
997std::pair<wifi_error, std::vector<wifi_tx_report>> WifiLegacyHal::getTxPktFates(
998 const std::string& iface_name) {
999 std::vector<wifi_tx_report> tx_pkt_fates;
1000 tx_pkt_fates.resize(MAX_FATE_LOG_LEN);
1001 size_t num_fates = 0;
1002 wifi_error status = global_func_table_.wifi_get_tx_pkt_fates(
1003 getIfaceHandle(iface_name), tx_pkt_fates.data(), tx_pkt_fates.size(), &num_fates);
1004 CHECK(num_fates <= MAX_FATE_LOG_LEN);
1005 tx_pkt_fates.resize(num_fates);
1006 return {status, std::move(tx_pkt_fates)};
1007}
1008
1009std::pair<wifi_error, std::vector<wifi_rx_report>> WifiLegacyHal::getRxPktFates(
1010 const std::string& iface_name) {
1011 std::vector<wifi_rx_report> rx_pkt_fates;
1012 rx_pkt_fates.resize(MAX_FATE_LOG_LEN);
1013 size_t num_fates = 0;
1014 wifi_error status = global_func_table_.wifi_get_rx_pkt_fates(
1015 getIfaceHandle(iface_name), rx_pkt_fates.data(), rx_pkt_fates.size(), &num_fates);
1016 CHECK(num_fates <= MAX_FATE_LOG_LEN);
1017 rx_pkt_fates.resize(num_fates);
1018 return {status, std::move(rx_pkt_fates)};
1019}
1020
1021std::pair<wifi_error, WakeReasonStats> WifiLegacyHal::getWakeReasonStats(
1022 const std::string& iface_name) {
1023 WakeReasonStats stats;
1024 stats.cmd_event_wake_cnt.resize(kMaxWakeReasonStatsArraySize);
1025 stats.driver_fw_local_wake_cnt.resize(kMaxWakeReasonStatsArraySize);
1026
1027 // This legacy struct needs separate memory to store the variable sized wake
1028 // reason types.
1029 stats.wake_reason_cnt.cmd_event_wake_cnt =
1030 reinterpret_cast<int32_t*>(stats.cmd_event_wake_cnt.data());
1031 stats.wake_reason_cnt.cmd_event_wake_cnt_sz = stats.cmd_event_wake_cnt.size();
1032 stats.wake_reason_cnt.cmd_event_wake_cnt_used = 0;
1033 stats.wake_reason_cnt.driver_fw_local_wake_cnt =
1034 reinterpret_cast<int32_t*>(stats.driver_fw_local_wake_cnt.data());
1035 stats.wake_reason_cnt.driver_fw_local_wake_cnt_sz = stats.driver_fw_local_wake_cnt.size();
1036 stats.wake_reason_cnt.driver_fw_local_wake_cnt_used = 0;
1037
1038 wifi_error status = global_func_table_.wifi_get_wake_reason_stats(getIfaceHandle(iface_name),
1039 &stats.wake_reason_cnt);
1040
1041 CHECK(stats.wake_reason_cnt.cmd_event_wake_cnt_used >= 0 &&
1042 static_cast<uint32_t>(stats.wake_reason_cnt.cmd_event_wake_cnt_used) <=
1043 kMaxWakeReasonStatsArraySize);
1044 stats.cmd_event_wake_cnt.resize(stats.wake_reason_cnt.cmd_event_wake_cnt_used);
1045 stats.wake_reason_cnt.cmd_event_wake_cnt = nullptr;
1046
1047 CHECK(stats.wake_reason_cnt.driver_fw_local_wake_cnt_used >= 0 &&
1048 static_cast<uint32_t>(stats.wake_reason_cnt.driver_fw_local_wake_cnt_used) <=
1049 kMaxWakeReasonStatsArraySize);
1050 stats.driver_fw_local_wake_cnt.resize(stats.wake_reason_cnt.driver_fw_local_wake_cnt_used);
1051 stats.wake_reason_cnt.driver_fw_local_wake_cnt = nullptr;
1052
1053 return {status, stats};
1054}
1055
1056wifi_error WifiLegacyHal::registerRingBufferCallbackHandler(
1057 const std::string& iface_name, const on_ring_buffer_data_callback& on_user_data_callback) {
1058 if (on_ring_buffer_data_internal_callback) {
1059 return WIFI_ERROR_NOT_AVAILABLE;
1060 }
1061 on_ring_buffer_data_internal_callback = [on_user_data_callback](
1062 char* ring_name, char* buffer, int buffer_size,
1063 wifi_ring_buffer_status* status) {
1064 if (status && buffer) {
1065 std::vector<uint8_t> buffer_vector(reinterpret_cast<uint8_t*>(buffer),
1066 reinterpret_cast<uint8_t*>(buffer) + buffer_size);
1067 on_user_data_callback(ring_name, buffer_vector, *status);
1068 }
1069 };
1070 wifi_error status = global_func_table_.wifi_set_log_handler(0, getIfaceHandle(iface_name),
1071 {onAsyncRingBufferData});
1072 if (status != WIFI_SUCCESS) {
1073 on_ring_buffer_data_internal_callback = nullptr;
1074 }
1075 return status;
1076}
1077
1078wifi_error WifiLegacyHal::deregisterRingBufferCallbackHandler(const std::string& iface_name) {
1079 if (!on_ring_buffer_data_internal_callback) {
1080 return WIFI_ERROR_NOT_AVAILABLE;
1081 }
1082 on_ring_buffer_data_internal_callback = nullptr;
1083 return global_func_table_.wifi_reset_log_handler(0, getIfaceHandle(iface_name));
1084}
1085
1086std::pair<wifi_error, std::vector<wifi_ring_buffer_status>> WifiLegacyHal::getRingBuffersStatus(
1087 const std::string& iface_name) {
1088 std::vector<wifi_ring_buffer_status> ring_buffers_status;
1089 ring_buffers_status.resize(kMaxRingBuffers);
1090 uint32_t num_rings = kMaxRingBuffers;
1091 wifi_error status = global_func_table_.wifi_get_ring_buffers_status(
1092 getIfaceHandle(iface_name), &num_rings, ring_buffers_status.data());
1093 CHECK(num_rings <= kMaxRingBuffers);
1094 ring_buffers_status.resize(num_rings);
1095 return {status, std::move(ring_buffers_status)};
1096}
1097
1098wifi_error WifiLegacyHal::startRingBufferLogging(const std::string& iface_name,
1099 const std::string& ring_name,
1100 uint32_t verbose_level, uint32_t max_interval_sec,
1101 uint32_t min_data_size) {
1102 return global_func_table_.wifi_start_logging(getIfaceHandle(iface_name), verbose_level, 0,
1103 max_interval_sec, min_data_size,
1104 makeCharVec(ring_name).data());
1105}
1106
1107wifi_error WifiLegacyHal::getRingBufferData(const std::string& iface_name,
1108 const std::string& ring_name) {
1109 return global_func_table_.wifi_get_ring_data(getIfaceHandle(iface_name),
1110 makeCharVec(ring_name).data());
1111}
1112
1113wifi_error WifiLegacyHal::registerErrorAlertCallbackHandler(
1114 const std::string& iface_name, const on_error_alert_callback& on_user_alert_callback) {
1115 if (on_error_alert_internal_callback) {
1116 return WIFI_ERROR_NOT_AVAILABLE;
1117 }
1118 on_error_alert_internal_callback = [on_user_alert_callback](wifi_request_id id, char* buffer,
1119 int buffer_size, int err_code) {
1120 if (buffer) {
1121 CHECK(id == 0);
1122 on_user_alert_callback(
1123 err_code,
1124 std::vector<uint8_t>(reinterpret_cast<uint8_t*>(buffer),
1125 reinterpret_cast<uint8_t*>(buffer) + buffer_size));
1126 }
1127 };
1128 wifi_error status = global_func_table_.wifi_set_alert_handler(0, getIfaceHandle(iface_name),
1129 {onAsyncErrorAlert});
1130 if (status != WIFI_SUCCESS) {
1131 on_error_alert_internal_callback = nullptr;
1132 }
1133 return status;
1134}
1135
1136wifi_error WifiLegacyHal::deregisterErrorAlertCallbackHandler(const std::string& iface_name) {
1137 if (!on_error_alert_internal_callback) {
1138 return WIFI_ERROR_NOT_AVAILABLE;
1139 }
1140 on_error_alert_internal_callback = nullptr;
1141 return global_func_table_.wifi_reset_alert_handler(0, getIfaceHandle(iface_name));
1142}
1143
1144wifi_error WifiLegacyHal::registerRadioModeChangeCallbackHandler(
1145 const std::string& iface_name,
1146 const on_radio_mode_change_callback& on_user_change_callback) {
1147 if (on_radio_mode_change_internal_callback) {
1148 return WIFI_ERROR_NOT_AVAILABLE;
1149 }
1150 on_radio_mode_change_internal_callback = [on_user_change_callback](
1151 wifi_request_id /* id */, uint32_t num_macs,
1152 wifi_mac_info* mac_infos_arr) {
1153 if (num_macs > 0 && mac_infos_arr) {
1154 std::vector<WifiMacInfo> mac_infos_vec;
1155 for (uint32_t i = 0; i < num_macs; i++) {
1156 WifiMacInfo mac_info;
1157 mac_info.wlan_mac_id = mac_infos_arr[i].wlan_mac_id;
1158 mac_info.mac_band = mac_infos_arr[i].mac_band;
1159 for (int32_t j = 0; j < mac_infos_arr[i].num_iface; j++) {
1160 WifiIfaceInfo iface_info;
1161 iface_info.name = mac_infos_arr[i].iface_info[j].iface_name;
1162 iface_info.channel = mac_infos_arr[i].iface_info[j].channel;
1163 mac_info.iface_infos.push_back(iface_info);
1164 }
1165 mac_infos_vec.push_back(mac_info);
1166 }
1167 on_user_change_callback(mac_infos_vec);
1168 }
1169 };
1170 wifi_error status = global_func_table_.wifi_set_radio_mode_change_handler(
1171 0, getIfaceHandle(iface_name), {onAsyncRadioModeChange});
1172 if (status != WIFI_SUCCESS) {
1173 on_radio_mode_change_internal_callback = nullptr;
1174 }
1175 return status;
1176}
1177
1178wifi_error WifiLegacyHal::registerSubsystemRestartCallbackHandler(
1179 const on_subsystem_restart_callback& on_restart_callback) {
1180 if (on_subsystem_restart_internal_callback) {
1181 return WIFI_ERROR_NOT_AVAILABLE;
1182 }
1183 on_subsystem_restart_internal_callback = [on_restart_callback](const char* error) {
1184 on_restart_callback(error);
1185 };
1186 wifi_error status = global_func_table_.wifi_set_subsystem_restart_handler(
1187 global_handle_, {onAsyncSubsystemRestart});
1188 if (status != WIFI_SUCCESS) {
1189 on_subsystem_restart_internal_callback = nullptr;
1190 }
1191 return status;
1192}
1193
1194wifi_error WifiLegacyHal::startRttRangeRequest(
1195 const std::string& iface_name, wifi_request_id id,
1196 const std::vector<wifi_rtt_config>& rtt_configs,
1197 const on_rtt_results_callback& on_results_user_callback) {
1198 if (on_rtt_results_internal_callback) {
1199 return WIFI_ERROR_NOT_AVAILABLE;
1200 }
1201
1202 on_rtt_results_internal_callback = [on_results_user_callback](wifi_request_id id,
1203 unsigned num_results,
1204 wifi_rtt_result* rtt_results[]) {
1205 if (num_results > 0 && !rtt_results) {
1206 LOG(ERROR) << "Unexpected nullptr in RTT results";
1207 return;
1208 }
1209 std::vector<const wifi_rtt_result*> rtt_results_vec;
1210 std::copy_if(rtt_results, rtt_results + num_results, back_inserter(rtt_results_vec),
1211 [](wifi_rtt_result* rtt_result) { return rtt_result != nullptr; });
1212 on_results_user_callback(id, rtt_results_vec);
1213 };
1214
1215 std::vector<wifi_rtt_config> rtt_configs_internal(rtt_configs);
1216 wifi_error status = global_func_table_.wifi_rtt_range_request(
1217 id, getIfaceHandle(iface_name), rtt_configs.size(), rtt_configs_internal.data(),
1218 {onAsyncRttResults});
1219 if (status != WIFI_SUCCESS) {
1220 on_rtt_results_internal_callback = nullptr;
1221 }
1222 return status;
1223}
1224
1225wifi_error WifiLegacyHal::cancelRttRangeRequest(
1226 const std::string& iface_name, wifi_request_id id,
1227 const std::vector<std::array<uint8_t, ETH_ALEN>>& mac_addrs) {
1228 if (!on_rtt_results_internal_callback) {
1229 return WIFI_ERROR_NOT_AVAILABLE;
1230 }
1231 static_assert(sizeof(mac_addr) == sizeof(std::array<uint8_t, ETH_ALEN>),
1232 "MAC address size mismatch");
1233 // TODO: How do we handle partial cancels (i.e only a subset of enabled mac
1234 // addressed are cancelled).
1235 std::vector<std::array<uint8_t, ETH_ALEN>> mac_addrs_internal(mac_addrs);
1236 wifi_error status = global_func_table_.wifi_rtt_range_cancel(
1237 id, getIfaceHandle(iface_name), mac_addrs.size(),
1238 reinterpret_cast<mac_addr*>(mac_addrs_internal.data()));
1239 // If the request Id is wrong, don't stop the ongoing range request. Any
1240 // other error should be treated as the end of rtt ranging.
1241 if (status != WIFI_ERROR_INVALID_REQUEST_ID) {
1242 on_rtt_results_internal_callback = nullptr;
1243 }
1244 return status;
1245}
1246
1247std::pair<wifi_error, wifi_rtt_capabilities> WifiLegacyHal::getRttCapabilities(
1248 const std::string& iface_name) {
1249 wifi_rtt_capabilities rtt_caps;
1250 wifi_error status =
1251 global_func_table_.wifi_get_rtt_capabilities(getIfaceHandle(iface_name), &rtt_caps);
1252 return {status, rtt_caps};
1253}
1254
1255std::pair<wifi_error, wifi_rtt_responder> WifiLegacyHal::getRttResponderInfo(
1256 const std::string& iface_name) {
1257 wifi_rtt_responder rtt_responder;
1258 wifi_error status = global_func_table_.wifi_rtt_get_responder_info(getIfaceHandle(iface_name),
1259 &rtt_responder);
1260 return {status, rtt_responder};
1261}
1262
1263wifi_error WifiLegacyHal::enableRttResponder(const std::string& iface_name, wifi_request_id id,
1264 const wifi_channel_info& channel_hint,
1265 uint32_t max_duration_secs,
1266 const wifi_rtt_responder& info) {
1267 wifi_rtt_responder info_internal(info);
1268 return global_func_table_.wifi_enable_responder(id, getIfaceHandle(iface_name), channel_hint,
1269 max_duration_secs, &info_internal);
1270}
1271
1272wifi_error WifiLegacyHal::disableRttResponder(const std::string& iface_name, wifi_request_id id) {
1273 return global_func_table_.wifi_disable_responder(id, getIfaceHandle(iface_name));
1274}
1275
1276wifi_error WifiLegacyHal::setRttLci(const std::string& iface_name, wifi_request_id id,
1277 const wifi_lci_information& info) {
1278 wifi_lci_information info_internal(info);
1279 return global_func_table_.wifi_set_lci(id, getIfaceHandle(iface_name), &info_internal);
1280}
1281
1282wifi_error WifiLegacyHal::setRttLcr(const std::string& iface_name, wifi_request_id id,
1283 const wifi_lcr_information& info) {
1284 wifi_lcr_information info_internal(info);
1285 return global_func_table_.wifi_set_lcr(id, getIfaceHandle(iface_name), &info_internal);
1286}
1287
1288wifi_error WifiLegacyHal::nanRegisterCallbackHandlers(const std::string& iface_name,
1289 const NanCallbackHandlers& user_callbacks) {
1290 on_nan_notify_response_user_callback = user_callbacks.on_notify_response;
1291 on_nan_event_publish_terminated_user_callback = user_callbacks.on_event_publish_terminated;
1292 on_nan_event_match_user_callback = user_callbacks.on_event_match;
1293 on_nan_event_match_expired_user_callback = user_callbacks.on_event_match_expired;
1294 on_nan_event_subscribe_terminated_user_callback = user_callbacks.on_event_subscribe_terminated;
1295 on_nan_event_followup_user_callback = user_callbacks.on_event_followup;
1296 on_nan_event_disc_eng_event_user_callback = user_callbacks.on_event_disc_eng_event;
1297 on_nan_event_disabled_user_callback = user_callbacks.on_event_disabled;
1298 on_nan_event_tca_user_callback = user_callbacks.on_event_tca;
1299 on_nan_event_beacon_sdf_payload_user_callback = user_callbacks.on_event_beacon_sdf_payload;
1300 on_nan_event_data_path_request_user_callback = user_callbacks.on_event_data_path_request;
1301 on_nan_event_data_path_confirm_user_callback = user_callbacks.on_event_data_path_confirm;
1302 on_nan_event_data_path_end_user_callback = user_callbacks.on_event_data_path_end;
1303 on_nan_event_transmit_follow_up_user_callback = user_callbacks.on_event_transmit_follow_up;
1304 on_nan_event_range_request_user_callback = user_callbacks.on_event_range_request;
1305 on_nan_event_range_report_user_callback = user_callbacks.on_event_range_report;
1306 on_nan_event_schedule_update_user_callback = user_callbacks.on_event_schedule_update;
1307
1308 return global_func_table_.wifi_nan_register_handler(
1309 getIfaceHandle(iface_name),
1310 {onAsyncNanNotifyResponse, onAsyncNanEventPublishReplied,
1311 onAsyncNanEventPublishTerminated, onAsyncNanEventMatch, onAsyncNanEventMatchExpired,
1312 onAsyncNanEventSubscribeTerminated, onAsyncNanEventFollowup,
1313 onAsyncNanEventDiscEngEvent, onAsyncNanEventDisabled, onAsyncNanEventTca,
1314 onAsyncNanEventBeaconSdfPayload, onAsyncNanEventDataPathRequest,
1315 onAsyncNanEventDataPathConfirm, onAsyncNanEventDataPathEnd,
1316 onAsyncNanEventTransmitFollowUp, onAsyncNanEventRangeRequest,
1317 onAsyncNanEventRangeReport, onAsyncNanEventScheduleUpdate});
1318}
1319
1320wifi_error WifiLegacyHal::nanEnableRequest(const std::string& iface_name, transaction_id id,
1321 const NanEnableRequest& msg) {
1322 NanEnableRequest msg_internal(msg);
1323 return global_func_table_.wifi_nan_enable_request(id, getIfaceHandle(iface_name),
1324 &msg_internal);
1325}
1326
1327wifi_error WifiLegacyHal::nanDisableRequest(const std::string& iface_name, transaction_id id) {
1328 return global_func_table_.wifi_nan_disable_request(id, getIfaceHandle(iface_name));
1329}
1330
1331wifi_error WifiLegacyHal::nanPublishRequest(const std::string& iface_name, transaction_id id,
1332 const NanPublishRequest& msg) {
1333 NanPublishRequest msg_internal(msg);
1334 return global_func_table_.wifi_nan_publish_request(id, getIfaceHandle(iface_name),
1335 &msg_internal);
1336}
1337
1338wifi_error WifiLegacyHal::nanPublishCancelRequest(const std::string& iface_name, transaction_id id,
1339 const NanPublishCancelRequest& msg) {
1340 NanPublishCancelRequest msg_internal(msg);
1341 return global_func_table_.wifi_nan_publish_cancel_request(id, getIfaceHandle(iface_name),
1342 &msg_internal);
1343}
1344
1345wifi_error WifiLegacyHal::nanSubscribeRequest(const std::string& iface_name, transaction_id id,
1346 const NanSubscribeRequest& msg) {
1347 NanSubscribeRequest msg_internal(msg);
1348 return global_func_table_.wifi_nan_subscribe_request(id, getIfaceHandle(iface_name),
1349 &msg_internal);
1350}
1351
1352wifi_error WifiLegacyHal::nanSubscribeCancelRequest(const std::string& iface_name,
1353 transaction_id id,
1354 const NanSubscribeCancelRequest& msg) {
1355 NanSubscribeCancelRequest msg_internal(msg);
1356 return global_func_table_.wifi_nan_subscribe_cancel_request(id, getIfaceHandle(iface_name),
1357 &msg_internal);
1358}
1359
1360wifi_error WifiLegacyHal::nanTransmitFollowupRequest(const std::string& iface_name,
1361 transaction_id id,
1362 const NanTransmitFollowupRequest& msg) {
1363 NanTransmitFollowupRequest msg_internal(msg);
1364 return global_func_table_.wifi_nan_transmit_followup_request(id, getIfaceHandle(iface_name),
1365 &msg_internal);
1366}
1367
1368wifi_error WifiLegacyHal::nanStatsRequest(const std::string& iface_name, transaction_id id,
1369 const NanStatsRequest& msg) {
1370 NanStatsRequest msg_internal(msg);
1371 return global_func_table_.wifi_nan_stats_request(id, getIfaceHandle(iface_name), &msg_internal);
1372}
1373
1374wifi_error WifiLegacyHal::nanConfigRequest(const std::string& iface_name, transaction_id id,
1375 const NanConfigRequest& msg) {
1376 NanConfigRequest msg_internal(msg);
1377 return global_func_table_.wifi_nan_config_request(id, getIfaceHandle(iface_name),
1378 &msg_internal);
1379}
1380
1381wifi_error WifiLegacyHal::nanTcaRequest(const std::string& iface_name, transaction_id id,
1382 const NanTCARequest& msg) {
1383 NanTCARequest msg_internal(msg);
1384 return global_func_table_.wifi_nan_tca_request(id, getIfaceHandle(iface_name), &msg_internal);
1385}
1386
1387wifi_error WifiLegacyHal::nanBeaconSdfPayloadRequest(const std::string& iface_name,
1388 transaction_id id,
1389 const NanBeaconSdfPayloadRequest& msg) {
1390 NanBeaconSdfPayloadRequest msg_internal(msg);
1391 return global_func_table_.wifi_nan_beacon_sdf_payload_request(id, getIfaceHandle(iface_name),
1392 &msg_internal);
1393}
1394
1395std::pair<wifi_error, NanVersion> WifiLegacyHal::nanGetVersion() {
1396 NanVersion version;
1397 wifi_error status = global_func_table_.wifi_nan_get_version(global_handle_, &version);
1398 return {status, version};
1399}
1400
1401wifi_error WifiLegacyHal::nanGetCapabilities(const std::string& iface_name, transaction_id id) {
1402 return global_func_table_.wifi_nan_get_capabilities(id, getIfaceHandle(iface_name));
1403}
1404
1405wifi_error WifiLegacyHal::nanDataInterfaceCreate(const std::string& iface_name, transaction_id id,
1406 const std::string& data_iface_name) {
1407 return global_func_table_.wifi_nan_data_interface_create(id, getIfaceHandle(iface_name),
1408 makeCharVec(data_iface_name).data());
1409}
1410
1411wifi_error WifiLegacyHal::nanDataInterfaceDelete(const std::string& iface_name, transaction_id id,
1412 const std::string& data_iface_name) {
1413 return global_func_table_.wifi_nan_data_interface_delete(id, getIfaceHandle(iface_name),
1414 makeCharVec(data_iface_name).data());
1415}
1416
1417wifi_error WifiLegacyHal::nanDataRequestInitiator(const std::string& iface_name, transaction_id id,
1418 const NanDataPathInitiatorRequest& msg) {
1419 NanDataPathInitiatorRequest msg_internal(msg);
1420 return global_func_table_.wifi_nan_data_request_initiator(id, getIfaceHandle(iface_name),
1421 &msg_internal);
1422}
1423
1424wifi_error WifiLegacyHal::nanDataIndicationResponse(const std::string& iface_name,
1425 transaction_id id,
1426 const NanDataPathIndicationResponse& msg) {
1427 NanDataPathIndicationResponse msg_internal(msg);
1428 return global_func_table_.wifi_nan_data_indication_response(id, getIfaceHandle(iface_name),
1429 &msg_internal);
1430}
1431
1432typedef struct {
1433 u8 num_ndp_instances;
1434 NanDataPathId ndp_instance_id;
1435} NanDataPathEndSingleNdpIdRequest;
1436
1437wifi_error WifiLegacyHal::nanDataEnd(const std::string& iface_name, transaction_id id,
1438 uint32_t ndpInstanceId) {
1439 NanDataPathEndSingleNdpIdRequest msg;
1440 msg.num_ndp_instances = 1;
1441 msg.ndp_instance_id = ndpInstanceId;
1442 wifi_error status = global_func_table_.wifi_nan_data_end(id, getIfaceHandle(iface_name),
1443 (NanDataPathEndRequest*)&msg);
1444 return status;
1445}
1446
1447wifi_error WifiLegacyHal::setCountryCode(const std::string& iface_name,
1448 const std::array<uint8_t, 2> code) {
1449 std::string code_str(code.data(), code.data() + code.size());
1450 return global_func_table_.wifi_set_country_code(getIfaceHandle(iface_name), code_str.c_str());
1451}
1452
1453wifi_error WifiLegacyHal::retrieveIfaceHandles() {
1454 wifi_interface_handle* iface_handles = nullptr;
1455 int num_iface_handles = 0;
1456 wifi_error status =
1457 global_func_table_.wifi_get_ifaces(global_handle_, &num_iface_handles, &iface_handles);
1458 if (status != WIFI_SUCCESS) {
1459 LOG(ERROR) << "Failed to enumerate interface handles";
1460 return status;
1461 }
1462 iface_name_to_handle_.clear();
1463 for (int i = 0; i < num_iface_handles; ++i) {
1464 std::array<char, IFNAMSIZ> iface_name_arr = {};
1465 status = global_func_table_.wifi_get_iface_name(iface_handles[i], iface_name_arr.data(),
1466 iface_name_arr.size());
1467 if (status != WIFI_SUCCESS) {
1468 LOG(WARNING) << "Failed to get interface handle name";
1469 continue;
1470 }
1471 // Assuming the interface name is null terminated since the legacy HAL
1472 // API does not return a size.
1473 std::string iface_name(iface_name_arr.data());
1474 LOG(INFO) << "Adding interface handle for " << iface_name;
1475 iface_name_to_handle_[iface_name] = iface_handles[i];
1476 }
1477 return WIFI_SUCCESS;
1478}
1479
1480wifi_interface_handle WifiLegacyHal::getIfaceHandle(const std::string& iface_name) {
1481 const auto iface_handle_iter = iface_name_to_handle_.find(iface_name);
1482 if (iface_handle_iter == iface_name_to_handle_.end()) {
1483 LOG(ERROR) << "Unknown iface name: " << iface_name;
1484 return nullptr;
1485 }
1486 return iface_handle_iter->second;
1487}
1488
1489void WifiLegacyHal::runEventLoop() {
1490 LOG(DEBUG) << "Starting legacy HAL event loop";
1491 global_func_table_.wifi_event_loop(global_handle_);
1492 const auto lock = aidl_sync_util::acquireGlobalLock();
1493 if (!awaiting_event_loop_termination_) {
1494 LOG(FATAL) << "Legacy HAL event loop terminated, but HAL was not stopping";
1495 }
1496 LOG(DEBUG) << "Legacy HAL event loop terminated";
1497 awaiting_event_loop_termination_ = false;
1498 stop_wait_cv_.notify_one();
1499}
1500
1501std::pair<wifi_error, std::vector<wifi_cached_scan_results>> WifiLegacyHal::getGscanCachedResults(
1502 const std::string& iface_name) {
1503 std::vector<wifi_cached_scan_results> cached_scan_results;
1504 cached_scan_results.resize(kMaxCachedGscanResults);
1505 int32_t num_results = 0;
1506 wifi_error status = global_func_table_.wifi_get_cached_gscan_results(
1507 getIfaceHandle(iface_name), true /* always flush */, cached_scan_results.size(),
1508 cached_scan_results.data(), &num_results);
1509 CHECK(num_results >= 0 && static_cast<uint32_t>(num_results) <= kMaxCachedGscanResults);
1510 cached_scan_results.resize(num_results);
1511 // Check for invalid IE lengths in these cached scan results and correct it.
1512 for (auto& cached_scan_result : cached_scan_results) {
1513 int num_scan_results = cached_scan_result.num_results;
1514 for (int i = 0; i < num_scan_results; i++) {
1515 auto& scan_result = cached_scan_result.results[i];
1516 if (scan_result.ie_length > 0) {
1517 LOG(DEBUG) << "Cached scan result has non-zero IE length " << scan_result.ie_length;
1518 scan_result.ie_length = 0;
1519 }
1520 }
1521 }
1522 return {status, std::move(cached_scan_results)};
1523}
1524
1525wifi_error WifiLegacyHal::createVirtualInterface(const std::string& ifname,
1526 wifi_interface_type iftype) {
1527 // Create the interface if it doesn't exist. If interface already exist,
1528 // Vendor Hal should return WIFI_SUCCESS.
1529 wifi_error status = global_func_table_.wifi_virtual_interface_create(global_handle_,
1530 ifname.c_str(), iftype);
1531 return handleVirtualInterfaceCreateOrDeleteStatus(ifname, status);
1532}
1533
1534wifi_error WifiLegacyHal::deleteVirtualInterface(const std::string& ifname) {
1535 // Delete the interface if it was created dynamically.
1536 wifi_error status =
1537 global_func_table_.wifi_virtual_interface_delete(global_handle_, ifname.c_str());
1538 return handleVirtualInterfaceCreateOrDeleteStatus(ifname, status);
1539}
1540
1541wifi_error WifiLegacyHal::handleVirtualInterfaceCreateOrDeleteStatus(const std::string& ifname,
1542 wifi_error status) {
1543 if (status == WIFI_SUCCESS) {
1544 // refresh list of handlers now.
1545 status = retrieveIfaceHandles();
1546 } else if (status == WIFI_ERROR_NOT_SUPPORTED) {
1547 // Vendor hal does not implement this API. Such vendor implementations
1548 // are expected to create / delete interface by other means.
1549
1550 // check if interface exists.
1551 if (if_nametoindex(ifname.c_str())) {
1552 status = retrieveIfaceHandles();
1553 }
1554 }
1555 return status;
1556}
1557
1558wifi_error WifiLegacyHal::getSupportedIfaceName(uint32_t iface_type, std::string& ifname) {
1559 std::array<char, IFNAMSIZ> buffer;
1560
1561 wifi_error res = global_func_table_.wifi_get_supported_iface_name(
1562 global_handle_, (uint32_t)iface_type, buffer.data(), buffer.size());
1563 if (res == WIFI_SUCCESS) ifname = buffer.data();
1564
1565 return res;
1566}
1567
1568wifi_error WifiLegacyHal::multiStaSetPrimaryConnection(const std::string& ifname) {
1569 return global_func_table_.wifi_multi_sta_set_primary_connection(global_handle_,
1570 getIfaceHandle(ifname));
1571}
1572
1573wifi_error WifiLegacyHal::multiStaSetUseCase(wifi_multi_sta_use_case use_case) {
1574 return global_func_table_.wifi_multi_sta_set_use_case(global_handle_, use_case);
1575}
1576
1577wifi_error WifiLegacyHal::setCoexUnsafeChannels(
1578 std::vector<wifi_coex_unsafe_channel> unsafe_channels, uint32_t restrictions) {
1579 return global_func_table_.wifi_set_coex_unsafe_channels(global_handle_, unsafe_channels.size(),
1580 unsafe_channels.data(), restrictions);
1581}
1582
1583wifi_error WifiLegacyHal::setVoipMode(const std::string& iface_name, wifi_voip_mode mode) {
1584 return global_func_table_.wifi_set_voip_mode(getIfaceHandle(iface_name), mode);
1585}
1586
1587wifi_error WifiLegacyHal::twtRegisterHandler(const std::string& iface_name,
1588 const TwtCallbackHandlers& user_callbacks) {
1589 on_twt_event_setup_response_callback = user_callbacks.on_setup_response;
1590 on_twt_event_teardown_completion_callback = user_callbacks.on_teardown_completion;
1591 on_twt_event_info_frame_received_callback = user_callbacks.on_info_frame_received;
1592 on_twt_event_device_notify_callback = user_callbacks.on_device_notify;
1593
1594 return global_func_table_.wifi_twt_register_handler(
1595 getIfaceHandle(iface_name),
1596 {onAsyncTwtEventSetupResponse, onAsyncTwtEventTeardownCompletion,
1597 onAsyncTwtEventInfoFrameReceived, onAsyncTwtEventDeviceNotify});
1598}
1599
1600std::pair<wifi_error, TwtCapabilitySet> WifiLegacyHal::twtGetCapability(
1601 const std::string& iface_name) {
1602 TwtCapabilitySet capSet;
1603 wifi_error status =
1604 global_func_table_.wifi_twt_get_capability(getIfaceHandle(iface_name), &capSet);
1605 return {status, capSet};
1606}
1607
1608wifi_error WifiLegacyHal::twtSetupRequest(const std::string& iface_name,
1609 const TwtSetupRequest& msg) {
1610 TwtSetupRequest msgInternal(msg);
1611 return global_func_table_.wifi_twt_setup_request(getIfaceHandle(iface_name), &msgInternal);
1612}
1613
1614wifi_error WifiLegacyHal::twtTearDownRequest(const std::string& iface_name,
1615 const TwtTeardownRequest& msg) {
1616 TwtTeardownRequest msgInternal(msg);
1617 return global_func_table_.wifi_twt_teardown_request(getIfaceHandle(iface_name), &msgInternal);
1618}
1619
1620wifi_error WifiLegacyHal::twtInfoFrameRequest(const std::string& iface_name,
1621 const TwtInfoFrameRequest& msg) {
1622 TwtInfoFrameRequest msgInternal(msg);
1623 return global_func_table_.wifi_twt_info_frame_request(getIfaceHandle(iface_name), &msgInternal);
1624}
1625
1626std::pair<wifi_error, TwtStats> WifiLegacyHal::twtGetStats(const std::string& iface_name,
1627 uint8_t configId) {
1628 TwtStats stats;
1629 wifi_error status =
1630 global_func_table_.wifi_twt_get_stats(getIfaceHandle(iface_name), configId, &stats);
1631 return {status, stats};
1632}
1633
1634wifi_error WifiLegacyHal::twtClearStats(const std::string& iface_name, uint8_t configId) {
1635 return global_func_table_.wifi_twt_clear_stats(getIfaceHandle(iface_name), configId);
1636}
1637
1638wifi_error WifiLegacyHal::setDtimConfig(const std::string& iface_name, uint32_t multiplier) {
1639 return global_func_table_.wifi_set_dtim_config(getIfaceHandle(iface_name), multiplier);
1640}
1641
1642std::pair<wifi_error, std::vector<wifi_usable_channel>> WifiLegacyHal::getUsableChannels(
1643 uint32_t band_mask, uint32_t iface_mode_mask, uint32_t filter_mask) {
1644 std::vector<wifi_usable_channel> channels;
1645 channels.resize(kMaxWifiUsableChannels);
1646 uint32_t size = 0;
1647 wifi_error status = global_func_table_.wifi_get_usable_channels(
1648 global_handle_, band_mask, iface_mode_mask, filter_mask, channels.size(), &size,
1649 reinterpret_cast<wifi_usable_channel*>(channels.data()));
1650 CHECK(size >= 0 && size <= kMaxWifiUsableChannels);
1651 channels.resize(size);
1652 return {status, std::move(channels)};
1653}
1654
1655wifi_error WifiLegacyHal::triggerSubsystemRestart() {
1656 return global_func_table_.wifi_trigger_subsystem_restart(global_handle_);
1657}
1658
1659wifi_error WifiLegacyHal::setIndoorState(bool isIndoor) {
1660 return global_func_table_.wifi_set_indoor_state(global_handle_, isIndoor);
1661}
1662
1663std::pair<wifi_error, wifi_radio_combination_matrix*>
1664WifiLegacyHal::getSupportedRadioCombinationsMatrix() {
1665 char* buffer = new char[kMaxSupportedRadioCombinationsMatrixLength];
1666 std::fill(buffer, buffer + kMaxSupportedRadioCombinationsMatrixLength, 0);
1667 uint32_t size = 0;
1668 wifi_radio_combination_matrix* radio_combination_matrix_ptr =
1669 reinterpret_cast<wifi_radio_combination_matrix*>(buffer);
1670 wifi_error status = global_func_table_.wifi_get_supported_radio_combinations_matrix(
1671 global_handle_, kMaxSupportedRadioCombinationsMatrixLength, &size,
1672 radio_combination_matrix_ptr);
1673 CHECK(size >= 0 && size <= kMaxSupportedRadioCombinationsMatrixLength);
1674 return {status, radio_combination_matrix_ptr};
1675}
1676
1677wifi_error WifiLegacyHal::chreNanRttRequest(const std::string& iface_name, bool enable) {
1678 if (enable)
1679 return global_func_table_.wifi_nan_rtt_chre_enable_request(0, getIfaceHandle(iface_name),
1680 NULL);
1681 else
1682 return global_func_table_.wifi_nan_rtt_chre_disable_request(0, getIfaceHandle(iface_name));
1683}
1684
1685wifi_error WifiLegacyHal::chreRegisterHandler(const std::string& iface_name,
1686 const ChreCallbackHandlers& handler) {
1687 if (on_chre_nan_rtt_internal_callback) {
1688 return WIFI_ERROR_NOT_AVAILABLE;
1689 }
1690
1691 on_chre_nan_rtt_internal_callback = handler.on_wifi_chre_nan_rtt_state;
1692
1693 wifi_error status = global_func_table_.wifi_chre_register_handler(getIfaceHandle(iface_name),
1694 {onAsyncChreNanRttState});
1695 if (status != WIFI_SUCCESS) {
1696 on_chre_nan_rtt_internal_callback = nullptr;
1697 }
1698 return status;
1699}
1700
1701wifi_error WifiLegacyHal::enableWifiTxPowerLimits(const std::string& iface_name, bool enable) {
1702 return global_func_table_.wifi_enable_tx_power_limits(getIfaceHandle(iface_name), enable);
1703}
1704
1705wifi_error WifiLegacyHal::getWifiCachedScanResults(
1706 const std::string& iface_name, const CachedScanResultsCallbackHandlers& handler) {
1707 on_cached_scan_results_internal_callback = handler.on_cached_scan_results;
1708
1709 wifi_error status = global_func_table_.wifi_get_cached_scan_results(getIfaceHandle(iface_name),
1710 {onSyncCachedScanResults});
1711
1712 on_cached_scan_results_internal_callback = nullptr;
1713 return status;
1714}
1715
Mahesh KKVc84d3772022-12-02 16:53:28 -08001716std::pair<wifi_error, wifi_chip_capabilities> WifiLegacyHal::getWifiChipCapabilities() {
1717 wifi_chip_capabilities chip_capabilities;
1718 wifi_error status =
1719 global_func_table_.wifi_get_chip_capabilities(global_handle_, &chip_capabilities);
1720 return {status, chip_capabilities};
1721}
1722
Gabriel Birenf3262f92022-07-15 23:25:39 +00001723void WifiLegacyHal::invalidate() {
1724 global_handle_ = nullptr;
1725 iface_name_to_handle_.clear();
1726 on_driver_memory_dump_internal_callback = nullptr;
1727 on_firmware_memory_dump_internal_callback = nullptr;
1728 on_gscan_event_internal_callback = nullptr;
1729 on_gscan_full_result_internal_callback = nullptr;
1730 on_link_layer_stats_result_internal_callback = nullptr;
Mahesh KKV5f30d332022-10-26 14:07:44 -07001731 on_link_layer_ml_stats_result_internal_callback = nullptr;
Gabriel Birenf3262f92022-07-15 23:25:39 +00001732 on_rssi_threshold_breached_internal_callback = nullptr;
1733 on_ring_buffer_data_internal_callback = nullptr;
1734 on_error_alert_internal_callback = nullptr;
1735 on_radio_mode_change_internal_callback = nullptr;
1736 on_subsystem_restart_internal_callback = nullptr;
1737 on_rtt_results_internal_callback = nullptr;
1738 on_nan_notify_response_user_callback = nullptr;
1739 on_nan_event_publish_terminated_user_callback = nullptr;
1740 on_nan_event_match_user_callback = nullptr;
1741 on_nan_event_match_expired_user_callback = nullptr;
1742 on_nan_event_subscribe_terminated_user_callback = nullptr;
1743 on_nan_event_followup_user_callback = nullptr;
1744 on_nan_event_disc_eng_event_user_callback = nullptr;
1745 on_nan_event_disabled_user_callback = nullptr;
1746 on_nan_event_tca_user_callback = nullptr;
1747 on_nan_event_beacon_sdf_payload_user_callback = nullptr;
1748 on_nan_event_data_path_request_user_callback = nullptr;
1749 on_nan_event_data_path_confirm_user_callback = nullptr;
1750 on_nan_event_data_path_end_user_callback = nullptr;
1751 on_nan_event_transmit_follow_up_user_callback = nullptr;
1752 on_nan_event_range_request_user_callback = nullptr;
1753 on_nan_event_range_report_user_callback = nullptr;
1754 on_nan_event_schedule_update_user_callback = nullptr;
1755 on_twt_event_setup_response_callback = nullptr;
1756 on_twt_event_teardown_completion_callback = nullptr;
1757 on_twt_event_info_frame_received_callback = nullptr;
1758 on_twt_event_device_notify_callback = nullptr;
1759 on_chre_nan_rtt_internal_callback = nullptr;
1760}
1761
1762} // namespace legacy_hal
1763} // namespace wifi
1764} // namespace hardware
1765} // namespace android
1766} // namespace aidl