• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
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 <cstdint>
18 #include <fcntl.h>
19 #include <sys/socket.h>
20 #include <netlink/genl/genl.h>
21 #include <netlink/genl/family.h>
22 #include <netlink/genl/ctrl.h>
23 #include <linux/rtnetlink.h>
24 #include <netpacket/packet.h>
25 #include <linux/filter.h>
26 #include <linux/errqueue.h>
27 
28 #include <linux/pkt_sched.h>
29 #include <netlink/object-api.h>
30 #include <netlink/netlink.h>
31 #include <netlink/socket.h>
32 #include <netlink/handlers.h>
33 
34 #include "wifi_hal.h"
35 #include "common.h"
36 #include "cpp_bindings.h"
37 #include "securec.h"
38 
39 #define MAX_CMD_SIZE 64
40 
41 /* test mode flag for halutil only */
42 bool g_halutilMode = false;
43 static std::shared_mutex g_rwMutex;
44 
ReadLockData()45 std::shared_lock<std::shared_mutex> ReadLockData()
46 {
47     return std::shared_lock<std::shared_mutex>{g_rwMutex};
48 }
49 
WriteLock()50 std::unique_lock<std::shared_mutex> WriteLock()
51 {
52     return std::unique_lock<std::shared_mutex>{g_rwMutex};
53 }
GetIfaceInfo(wifiInterfaceHandle handle)54 InterfaceInfo *GetIfaceInfo(wifiInterfaceHandle handle)
55 {
56     return (InterfaceInfo *)handle;
57 }
58 
GetWifiHandle(wifiInterfaceHandle handle)59 wifiHandle GetWifiHandle(wifiInterfaceHandle handle)
60 {
61     InterfaceInfo *info = GetIfaceInfo(handle);
62     if (info != nullptr) {
63         return GetIfaceInfo(handle)->handle;
64     }
65     return nullptr;
66 }
67 
GetHalInfo(wifiHandle handle)68 HalInfo *GetHalInfo(wifiHandle handle)
69 {
70     return (HalInfo *)handle;
71 }
72 
GetHalInfo(wifiInterfaceHandle handle)73 HalInfo *GetHalInfo(wifiInterfaceHandle handle)
74 {
75     return GetHalInfo(GetWifiHandle(handle));
76 }
77 
GetWifiHandle(HalInfo * info)78 wifiHandle GetWifiHandle(HalInfo *info)
79 {
80     return (wifiHandle)info;
81 }
82 
GetIfaceHandle(InterfaceInfo * info)83 wifiInterfaceHandle GetIfaceHandle(InterfaceInfo *info)
84 {
85     return (wifiInterfaceHandle)info;
86 }
87 
WifiRegisterHandler(wifiHandle handle,int cmd,nl_recvmsg_msg_cb_t func,void * arg)88 WifiError WifiRegisterHandler(wifiHandle handle, int cmd, nl_recvmsg_msg_cb_t func, void *arg)
89 {
90     HalInfo *info = (HalInfo *)handle;
91     pthread_mutex_lock(&info->cbLock);
92     WifiError result = HAL_OUT_OF_MEMORY;
93 
94     if (info->numEventCb < info->allocEventCb) {
95         info->eventCb[info->numEventCb].nlCmd  = cmd;
96         info->eventCb[info->numEventCb].vendorId  = 0;
97         info->eventCb[info->numEventCb].vendorSubcmd  = 0;
98         info->eventCb[info->numEventCb].cbFunc = func;
99         info->eventCb[info->numEventCb].cbArg  = arg;
100         HDF_LOGD("Successfully added event handler %{public}p:%{public}p for command %{public}d at %{public}d",
101             arg, func, cmd, info->numEventCb);
102         info->numEventCb++;
103         result = HAL_SUCCESS;
104     }
105 
106     pthread_mutex_unlock(&info->cbLock);
107     return result;
108 }
109 
WifiRegisterVendorHandler(wifiHandle handle,uint32_t id,int subcmd,nl_recvmsg_msg_cb_t func,void * arg)110 WifiError WifiRegisterVendorHandler(wifiHandle handle,
111     uint32_t id, int subcmd, nl_recvmsg_msg_cb_t func, void *arg)
112 {
113     HalInfo *info = (HalInfo *)handle;
114     pthread_mutex_lock(&info->cbLock);
115     WifiError result = HAL_OUT_OF_MEMORY;
116     if (info->numEventCb < info->allocEventCb) {
117         int i = 0;
118         bool isUpdate = false;
119         for (i = 0; i < info->numEventCb; i++) {
120             if ((info->eventCb[i].nlCmd == NL80211_CMD_VENDOR) &&
121                 (info->eventCb[i].vendorId == id) &&
122                 (info->eventCb[i].vendorSubcmd == subcmd)) {
123                 isUpdate = true;
124                 break;
125             }
126         }
127         if (isUpdate) {
128             info->eventCb[i].cbFunc = func;
129             info->eventCb[i].cbArg = arg;
130         } else {
131             info->eventCb[info->numEventCb].nlCmd  = NL80211_CMD_VENDOR;
132             info->eventCb[info->numEventCb].vendorId  = id;
133             info->eventCb[info->numEventCb].vendorSubcmd  = subcmd;
134             info->eventCb[info->numEventCb].cbFunc = func;
135             info->eventCb[info->numEventCb].cbArg  = arg;
136             info->numEventCb++;
137         }
138         HDF_LOGI("%{public}s ""event handler for vendor 0x%{public}0x and subcmd 0x%{public}0x at %{public}d",
139             isUpdate ? "Updated" : "Added", id, subcmd, info->numEventCb);
140         result = HAL_SUCCESS;
141     }
142 
143     pthread_mutex_unlock(&info->cbLock);
144     return result;
145 }
146 
WifiUnregisterHandler(wifiHandle handle,int cmd)147 void WifiUnregisterHandler(wifiHandle handle, int cmd)
148 {
149     HalInfo *info = (HalInfo *)handle;
150 
151     if (cmd == NL80211_CMD_VENDOR) {
152         HDF_LOGE("Must use WifiUnregisterVendorHandler to remove vendor handlers");
153         return;
154     }
155 
156     pthread_mutex_lock(&info->cbLock);
157 
158     for (int i = 0; i < info->numEventCb; i++) {
159         if (info->eventCb[i].nlCmd == cmd) {
160             HDF_LOGD("Successfully removed event handler for cmd = 0x%{public}0x from %{public}d",
161                      cmd, i);
162 
163             if (memmove_s(&info->eventCb[i], (info->numEventCb - i) * sizeof(CbInfo), &info->eventCb[i + 1],
164                 (info->numEventCb - i - 1) * sizeof(CbInfo)) != EOK) {
165                 break;
166             }
167             info->numEventCb--;
168             break;
169         }
170     }
171 
172     pthread_mutex_unlock(&info->cbLock);
173 }
174 
WifiUnregisterVendorHandlerWithoutLock(wifiHandle handle,uint32_t id,int subcmd)175 void WifiUnregisterVendorHandlerWithoutLock(wifiHandle handle, uint32_t id, int subcmd)
176 {
177     HalInfo *info = (HalInfo *)handle;
178 
179     for (int i = 0; i < info->numEventCb; i++) {
180         if (info->eventCb[i].nlCmd == NL80211_CMD_VENDOR &&
181             info->eventCb[i].vendorId == id &&
182             info->eventCb[i].vendorSubcmd == subcmd) {
183             HDF_LOGI("Successfully removed event handler for vendor 0x%{public}0x,"
184                 "subcmd 0x%{public}0x from %{public}d", id, subcmd, i);
185             if (memmove_s(&info->eventCb[i], (info->numEventCb - i) * sizeof(CbInfo), &info->eventCb[i + 1],
186                 (info->numEventCb - i - 1) * sizeof(CbInfo)) != EOK) {
187                 break;
188             }
189             break;
190         }
191     }
192 }
193 
WifiUnregisterVendorHandler(wifiHandle handle,uint32_t id,int subcmd)194 void WifiUnregisterVendorHandler(wifiHandle handle, uint32_t id, int subcmd)
195 {
196     HalInfo *info = (HalInfo *)handle;
197 
198     pthread_mutex_lock(&info->cbLock);
199     WifiUnregisterVendorHandlerWithoutLock(handle, id, subcmd);
200     pthread_mutex_unlock(&info->cbLock);
201 }
202 
203 
WifiRegisterCmd(wifiHandle handle,int id,WifiCommand * cmd)204 WifiError WifiRegisterCmd(wifiHandle handle, int id, WifiCommand *cmd)
205 {
206     HalInfo *info = (HalInfo *)handle;
207 
208     HDF_LOGD("registering command %{public}d", id);
209 
210     WifiError result = HAL_OUT_OF_MEMORY;
211     if (info == nullptr) {
212         HDF_LOGE("wifi info is null");
213         return result;
214     }
215     if (info->numCmd < info->allocCmd) {
216         info->cmd[info->numCmd].id   = id;
217         info->cmd[info->numCmd].cmd  = cmd;
218         HDF_LOGD("Successfully added command %{public}d: at %{public}d", id, info->numCmd);
219         info->numCmd++;
220         result = HAL_SUCCESS;
221     } else {
222         HDF_LOGE("Failed to add command %{public}d: at %{public}d, reached MAX limit %{public}d",
223             id, info->numCmd, info->allocCmd);
224     }
225 
226     return result;
227 }
228 
WifiUnregisterCmd(wifiHandle handle,int id)229 WifiCommand *WifiUnregisterCmd(wifiHandle handle, int id)
230 {
231     HalInfo *info = (HalInfo *)handle;
232 
233     HDF_LOGD("un-registering command %{public}d", id);
234 
235     WifiCommand *cmd = nullptr;
236 
237     if (info->numCmd > MAX_CMD_SIZE) {
238         HDF_LOGE("invilid cmd size");
239         return cmd;
240     }
241     for (int i = 0; i < info->numCmd; i++) {
242         if (info->cmd[i].id == id) {
243             cmd = info->cmd[i].cmd;
244             if (memmove_s(&info->cmd[i], (info->numCmd - i) * sizeof(CmdInfo), &info->cmd[i + 1],
245                 (info->numCmd - i - 1) * sizeof(CmdInfo)) != EOK) {
246                 break;
247             }
248             info->numCmd--;
249             HDF_LOGD("Successfully removed command %{public}d: from %{public}d", id, i);
250             break;
251         }
252     }
253 
254     if (!cmd) {
255         HDF_LOGI("Failed to remove command %{public}d", id);
256     }
257 
258     return cmd;
259 }
260 
WifiUnregisterCmd(wifiHandle handle,WifiCommand * cmd)261 void WifiUnregisterCmd(wifiHandle handle, WifiCommand *cmd)
262 {
263     HalInfo *info = (HalInfo *)handle;
264 
265     for (int i = 0; i < info->numCmd; i++) {
266         if (info->cmd[i].cmd == cmd) {
267             int id = info->cmd[i].id;
268             if (memmove_s(&info->cmd[i], (info->numCmd - i) * sizeof(CmdInfo), &info->cmd[i + 1],
269                 (info->numCmd - i - 1) * sizeof(CmdInfo)) != EOK) {
270                 break;
271             }
272             info->numCmd--;
273             HDF_LOGD("Successfully removed command %{public}d: from %{public}d", id, i);
274             break;
275         }
276     }
277 }
278 
SetHautilMode(bool halutilMode)279 void SetHautilMode(bool halutilMode)
280 {
281     g_halutilMode = halutilMode;
282 }
GetGHalutilMode()283 bool GetGHalutilMode()
284 {
285     return g_halutilMode;
286 }
287