1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <array>
17 #include <chrono>
18 #include <net/if.h>
19 #include <csignal>
20 #include "wifi_vendor_hal.h"
21 #include <hdf_log.h>
22 #include "hdi_sync_util.h"
23 #include "parameter.h"
24 #include "wifi_sta_iface.h"
25
26 static constexpr uint32_t K_MAX_STOP_COMPLETE_WAIT_MS = 1000;
27
28 namespace OHOS {
29 namespace HDI {
30 namespace Wlan {
31 namespace Chip {
32 namespace V1_0 {
33 std::function<void(wifiHandle handle)> onStopCompleteCallback;
34 std::function<void(const char*)> onVendorHalRestartCallback;
35 std::function<void(int)> onFullScanResultCallback;
36
OnAsyncStopComplete(wifiHandle handle)37 void OnAsyncStopComplete(wifiHandle handle)
38 {
39 const auto lock = AcquireGlobalLock();
40 if (onStopCompleteCallback) {
41 onStopCompleteCallback(handle);
42 onStopCompleteCallback = nullptr;
43 }
44 }
45
OnAsyncSubsystemRestart(const char * error)46 void OnAsyncSubsystemRestart(const char* error)
47 {
48 const auto lock = AcquireGlobalLock();
49 if (onVendorHalRestartCallback) {
50 onVendorHalRestartCallback(error);
51 }
52 }
53
54 CallbackHandler<IChipIfaceCallback> WifiVendorHal::vendorHalCbHandler_;
WifiVendorHal(const std::weak_ptr<IfaceTool> ifaceTool,const WifiHalFn & fn,bool isPrimary)55 WifiVendorHal::WifiVendorHal(
56 const std::weak_ptr<IfaceTool> ifaceTool,
57 const WifiHalFn& fn, bool isPrimary)
58 : globalFuncTable_(fn),
59 globalHandle_(nullptr),
60 awaitingEventLoopTermination_(false),
61 isInited_(false),
62 ifaceTool_(ifaceTool),
63 isPrimary_(isPrimary) {
64 }
65
Initialize()66 WifiError WifiVendorHal::Initialize()
67 {
68 HDF_LOGI("Initialize vendor HAL");
69 return HAL_SUCCESS;
70 }
71
Start()72 WifiError WifiVendorHal::Start()
73 {
74 if (!globalFuncTable_.vendorHalInit || globalHandle_ ||
75 !ifaceNameHandle_.empty() || awaitingEventLoopTermination_) {
76 return HAL_UNKNOWN;
77 }
78 if (isInited_) {
79 HDF_LOGI("Vendor HAL already started");
80 return HAL_SUCCESS;
81 }
82 HDF_LOGI("Waiting for the driver ready");
83 WifiError status = globalFuncTable_.waitDriverStart();
84 if (status == HAL_TIMED_OUT || status == HAL_UNKNOWN) {
85 HDF_LOGE("Failed or timed out awaiting driver ready");
86 return status;
87 }
88 HDF_LOGI("Starting vendor HAL");
89 status = globalFuncTable_.vendorHalInit(&globalHandle_);
90 if (status != HAL_SUCCESS || !globalHandle_) {
91 HDF_LOGE("Failed to retrieve global handle");
92 return status;
93 }
94 std::thread(&WifiVendorHal::RunEventLoop, this).detach();
95 status = RetrieveIfaceHandles();
96 if (status != HAL_SUCCESS || ifaceNameHandle_.empty()) {
97 HDF_LOGE("Failed to retrieve wlan interface handle");
98 return status;
99 }
100 HDF_LOGI("Vendor HAL start complete");
101 isInited_ = true;
102 return HAL_SUCCESS;
103 }
104
RunEventLoop()105 void WifiVendorHal::RunEventLoop()
106 {
107 HDF_LOGD("Starting vendor HAL event loop");
108 globalFuncTable_.startHalLoop(globalHandle_);
109 const auto lock = AcquireGlobalLock();
110 if (!awaitingEventLoopTermination_) {
111 HDF_LOGE("Vendor HAL event loop terminated, but HAL was not stopping");
112 }
113 HDF_LOGD("Vendor HAL event loop terminated");
114 awaitingEventLoopTermination_ = false;
115 stopWaitCv_.notify_one();
116 }
117
OnAsyncGscanFullResult(int event)118 void WifiVendorHal::OnAsyncGscanFullResult(int event)
119 {
120 const auto lock = AcquireGlobalLock();
121
122 HDF_LOGD("OnAsyncGscanFullResult::OnScanResultsCallback");
123 for (const auto& callback : vendorHalCbHandler_.GetCallbacks()) {
124 if (callback) {
125 callback->OnScanResultsCallback(event);
126 }
127 }
128 }
129
OnAsyncRssiReport(int32_t index,int32_t c0Rssi,int32_t c1Rssi)130 void WifiVendorHal::OnAsyncRssiReport(int32_t index, int32_t c0Rssi, int32_t c1Rssi)
131 {
132 const auto lock = AcquireGlobalLock();
133
134 HDF_LOGD("OnAsyncRssiReport::OnRssiReport");
135 for (const auto& callback : vendorHalCbHandler_.GetCallbacks()) {
136 if (callback) {
137 callback->OnRssiReport(index, c0Rssi, c1Rssi);
138 }
139 }
140 }
141
Stop(std::unique_lock<std::recursive_mutex> * lock,const std::function<void ()> & onStopCompleteUserCallback)142 WifiError WifiVendorHal::Stop(std::unique_lock<std::recursive_mutex>* lock,
143 const std::function<void()>& onStopCompleteUserCallback)
144 {
145 if (!isInited_) {
146 HDF_LOGE("Vendor HAL already stopped");
147 onStopCompleteUserCallback();
148 return HAL_SUCCESS;
149 }
150 HDF_LOGD("Stopping vendor HAL");
151 onStopCompleteCallback = [onStopCompleteUserCallback,
152 this](wifiHandle handle) {
153 if (globalHandle_ != handle) {
154 HDF_LOGE("handle mismatch");
155 }
156 HDF_LOGI("Vendor HAL stop complete callback received");
157 Invalidate();
158 if (isPrimary_) ifaceTool_.lock()->SetWifiUpState(false);
159 onStopCompleteUserCallback();
160 isInited_ = false;
161 };
162 awaitingEventLoopTermination_ = true;
163 globalFuncTable_.vendorHalExit(globalHandle_, OnAsyncStopComplete);
164 const auto status = stopWaitCv_.wait_for(
165 *lock, std::chrono::milliseconds(K_MAX_STOP_COMPLETE_WAIT_MS),
166 [this] { return !awaitingEventLoopTermination_; });
167 if (!status) {
168 HDF_LOGE("Vendor HAL stop failed or timed out");
169 return HAL_UNKNOWN;
170 }
171 HDF_LOGE("Vendor HAL stop complete");
172 return HAL_SUCCESS;
173 }
174
GetIfaceHandle(const std::string & ifaceName)175 wifiInterfaceHandle WifiVendorHal::GetIfaceHandle(const std::string& ifaceName)
176 {
177 const auto iface_handle_iter = ifaceNameHandle_.find(ifaceName);
178 if (iface_handle_iter == ifaceNameHandle_.end()) {
179 HDF_LOGE("Unknown iface name: %{public}s", ifaceName.c_str());
180 return nullptr;
181 }
182 return iface_handle_iter->second;
183 }
184
GetChipCaps(const std::string & ifaceName,uint32_t & capabilities)185 WifiError WifiVendorHal::GetChipCaps(const std::string& ifaceName, uint32_t& capabilities)
186 {
187 capabilities = globalFuncTable_.getChipCaps(ifaceName.c_str());
188 if (capabilities == 0) {
189 return HAL_UNKNOWN;
190 }
191 return HAL_SUCCESS;
192 }
193
GetSupportedFeatureSet(const std::string & ifaceName,uint32_t & capabilities)194 WifiError WifiVendorHal::GetSupportedFeatureSet(const std::string& ifaceName, uint32_t& capabilities)
195 {
196 capabilities = globalFuncTable_.wifiGetSupportedFeatureSet(ifaceName.c_str());
197 if (capabilities == 0) {
198 return HAL_UNKNOWN;
199 }
200 return HAL_SUCCESS;
201 }
202
GetValidFrequenciesForBand(const std::string & ifaceName,int band)203 std::pair<WifiError, std::vector<uint32_t>>WifiVendorHal::GetValidFrequenciesForBand(
204 const std::string& ifaceName, int band)
205 {
206 std::vector<uint32_t> freqs;
207
208 WifiError status = globalFuncTable_.vendorHalGetChannelsInBand(
209 GetIfaceHandle(ifaceName), band, freqs);
210 return {status, std::move(freqs)};
211 }
212
CreateVirtualInterface(const std::string & ifname,HalIfaceType iftype)213 WifiError WifiVendorHal::CreateVirtualInterface(const std::string& ifname, HalIfaceType iftype)
214 {
215 WifiError status = globalFuncTable_.vendorHalCreateIface(
216 globalHandle_, ifname.c_str(), iftype);
217 status = HandleIfaceChangeStatus(ifname, status);
218 if (status == HAL_SUCCESS && iftype == HalIfaceType::HAL_TYPE_STA) {
219 ifaceTool_.lock()->SetUpState(ifname.c_str(), true);
220 }
221 return status;
222 }
223
DeleteVirtualInterface(const std::string & ifname)224 WifiError WifiVendorHal::DeleteVirtualInterface(const std::string& ifname)
225 {
226 WifiError status = globalFuncTable_.vendorHalDeleteIface(
227 globalHandle_, ifname.c_str());
228 return HandleIfaceChangeStatus(ifname, status);
229 }
230
HandleIfaceChangeStatus(const std::string & ifname,WifiError status)231 WifiError WifiVendorHal::HandleIfaceChangeStatus(
232 const std::string& ifname, WifiError status)
233 {
234 if (status == HAL_SUCCESS) {
235 status = RetrieveIfaceHandles();
236 } else if (status == HAL_NOT_SUPPORTED) {
237 if (if_nametoindex(ifname.c_str())) {
238 status = RetrieveIfaceHandles();
239 }
240 }
241 return status;
242 }
243
RetrieveIfaceHandles()244 WifiError WifiVendorHal::RetrieveIfaceHandles()
245 {
246 wifiInterfaceHandle* ifaceHandles = nullptr;
247 int numIfaceHandles = 0;
248 WifiError status = globalFuncTable_.vendorHalGetIfaces(
249 globalHandle_, &numIfaceHandles, &ifaceHandles);
250 if (status != HAL_SUCCESS) {
251 HDF_LOGE("Failed to enumerate interface handles");
252 return status;
253 }
254 ifaceNameHandle_.clear();
255 for (int i = 0; i < numIfaceHandles; ++i) {
256 std::array<char, IFNAMSIZ> iface_name_arr = {};
257 status = globalFuncTable_.vendorHalGetIfName(
258 ifaceHandles[i], iface_name_arr.data(), iface_name_arr.size());
259 if (status != HAL_SUCCESS) {
260 HDF_LOGE("Failed to get interface handle name");
261 continue;
262 }
263 std::string ifaceName(iface_name_arr.data());
264 HDF_LOGI("Adding interface handle for %{public}s", ifaceName.c_str());
265 ifaceNameHandle_[ifaceName] = ifaceHandles[i];
266 }
267 return HAL_SUCCESS;
268 }
269
RegisterRestartCallback(const OnVendorHalRestartCallback & onRestartCallback)270 WifiError WifiVendorHal::RegisterRestartCallback(
271 const OnVendorHalRestartCallback& onRestartCallback)
272 {
273 if (onVendorHalRestartCallback) {
274 return HAL_NOT_AVAILABLE;
275 }
276 onVendorHalRestartCallback =
277 [onRestartCallback](const char* error) {
278 onRestartCallback(error);
279 };
280 WifiError status = globalFuncTable_.vendorHalSetRestartHandler(
281 globalHandle_, {OnAsyncSubsystemRestart});
282 if (status != HAL_SUCCESS) {
283 onVendorHalRestartCallback = nullptr;
284 }
285 return status;
286 }
287
Invalidate()288 void WifiVendorHal::Invalidate()
289 {
290 globalHandle_ = nullptr;
291 ifaceNameHandle_.clear();
292 vendorHalCbHandler_.Invalidate();
293 }
294
SetCountryCode(const std::string & ifaceName,const std::string & code)295 WifiError WifiVendorHal::SetCountryCode(const std::string& ifaceName, const std::string& code)
296 {
297 return globalFuncTable_.wifiSetCountryCode(GetIfaceHandle(ifaceName), code.c_str());
298 }
299
GetSignalPollInfo(const std::string & ifaceName,SignalPollResult & signalPollResult)300 WifiError WifiVendorHal::GetSignalPollInfo(const std::string& ifaceName,
301 SignalPollResult& signalPollResult)
302 {
303 return globalFuncTable_.getSignalPollInfo(GetIfaceHandle(ifaceName), signalPollResult);
304 }
305
GetPowerMode(const std::string & ifaceName)306 std::pair<WifiError, int> WifiVendorHal::GetPowerMode(const std::string& ifaceName)
307 {
308 int mode;
309 WifiError status = globalFuncTable_.getPowerMode(ifaceName.c_str(), &mode);
310 return {status, mode};
311 }
312
SetPowerMode(const std::string & ifaceName,int mode)313 WifiError WifiVendorHal::SetPowerMode(const std::string& ifaceName, int mode)
314 {
315 return globalFuncTable_.setPowerMode(ifaceName.c_str(), mode);
316 }
317
IsSupportCoex(bool & isCoex)318 WifiError WifiVendorHal::IsSupportCoex(bool& isCoex)
319 {
320 return globalFuncTable_.isSupportCoex(isCoex);
321 }
322
EnablePowerMode(const std::string & ifaceName,int mode)323 WifiError WifiVendorHal::EnablePowerMode(const std::string& ifaceName, int mode)
324 {
325 return globalFuncTable_.enablePowerMode(ifaceName.c_str(), mode);
326 }
327
StartScan(const std::string & ifaceName,const ScanParams & params)328 WifiError WifiVendorHal::StartScan(
329 const std::string& ifaceName, const ScanParams& params)
330 {
331 WifiError status = globalFuncTable_.wifiStartScan(GetIfaceHandle(ifaceName), params);
332 return status;
333 }
334
StartPnoScan(const std::string & ifaceName,const PnoScanParams & pnoParams)335 WifiError WifiVendorHal::StartPnoScan(const std::string& ifaceName, const PnoScanParams& pnoParams)
336 {
337 WifiError status = globalFuncTable_.wifiStartPnoScan(GetIfaceHandle(ifaceName), pnoParams);
338 return status;
339 }
340
StopPnoScan(const std::string & ifaceName)341 WifiError WifiVendorHal::StopPnoScan(const std::string& ifaceName)
342 {
343 WifiError status = globalFuncTable_.wifiStopPnoScan(GetIfaceHandle(ifaceName));
344 return status;
345 }
346
GetScanInfos(const std::string & ifaceName,std::vector<ScanResultsInfo> & scanResultsInfo)347 WifiError WifiVendorHal::GetScanInfos(const std::string& ifaceName,
348 std::vector<ScanResultsInfo>& scanResultsInfo)
349 {
350 WifiError status = globalFuncTable_.getScanResults(GetIfaceHandle(ifaceName), scanResultsInfo);
351 return status;
352 }
353
SetDpiMarkRule(int32_t uid,int32_t protocol,int32_t enable)354 WifiError WifiVendorHal::SetDpiMarkRule(int32_t uid, int32_t protocol, int32_t enable)
355 {
356 return globalFuncTable_.setDpiMarkRule(uid, protocol, enable);
357 }
358
RegisterIfaceCallBack(const std::string & ifaceName,const sptr<IChipIfaceCallback> & chipIfaceCallback)359 WifiError WifiVendorHal::RegisterIfaceCallBack(const std::string& ifaceName,
360 const sptr<IChipIfaceCallback>& chipIfaceCallback)
361 {
362 vendorHalCbHandler_.AddCallback(chipIfaceCallback);
363 WifiCallbackHandler handler = {OnAsyncGscanFullResult, OnAsyncRssiReport};
364 globalFuncTable_.registerIfaceCallBack(ifaceName.c_str(), handler);
365 return HAL_SUCCESS;
366 }
367
UnRegisterIfaceCallBack(const std::string & ifaceName,const sptr<IChipIfaceCallback> & chipIfaceCallback)368 WifiError WifiVendorHal::UnRegisterIfaceCallBack(const std::string& ifaceName,
369 const sptr<IChipIfaceCallback>& chipIfaceCallback)
370 {
371 WifiCallbackHandler handler = {};
372 globalFuncTable_.registerIfaceCallBack(ifaceName.c_str(), handler);
373 vendorHalCbHandler_.Invalidate(); // instead of RemoveCallback temporarily
374 return HAL_SUCCESS;
375 }
376
SetTxPower(const std::string & ifaceName,int mode)377 WifiError WifiVendorHal::SetTxPower(const std::string& ifaceName, int mode)
378 {
379 return globalFuncTable_.setTxPower(ifaceName.c_str(), mode);
380 }
381
382 } // namespace v1_0
383 } // namespace Chip
384 } // namespace Wlan
385 } // namespace HDI
386 } // namespace OHOS