1 /*
2 * hdf_bdh_mac80211.c
3 *
4 * hdf driver
5 *
6 * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd.
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 */
18 #include <net/cfg80211.h>
19 #include <net/regulatory.h>
20 #include <securec.h>
21 #include <linux/version.h>
22
23 #include "wifi_module.h"
24 #include "wifi_mac80211_ops.h"
25 #include "hdf_wlan_utils.h"
26 #include "net_bdh_adpater.h"
27 #include "hdf_wl_interface.h"
28 #include "hdf_public_ap6256.h"
29 #include "hdf_mac80211_sta.h"
30
31 #define HDF_LOG_TAG BDH6Driver
32
33 struct NetDevice *get_real_netdev(NetDevice *netDev);
34 int32_t WalStopAp(NetDevice *netDev);
get_linux_wiphy_ndev(struct net_device * ndev)35 struct wiphy *get_linux_wiphy_ndev(struct net_device *ndev)
36 {
37 if (ndev == NULL || ndev->ieee80211_ptr == NULL) {
38 return NULL;
39 }
40
41 return ndev->ieee80211_ptr->wiphy;
42 }
43
get_linux_wiphy_hdfdev(NetDevice * netDev)44 struct wiphy *get_linux_wiphy_hdfdev(NetDevice *netDev)
45 {
46 struct net_device *ndev = GetLinuxInfByNetDevice(netDev);
47 return get_linux_wiphy_ndev(ndev);
48 }
49
BDH6WalSetMode(NetDevice * hnetDev,enum WlanWorkMode iftype)50 int32_t BDH6WalSetMode(NetDevice *hnetDev, enum WlanWorkMode iftype)
51 {
52 int32_t retVal = 0;
53 struct net_device *netdev = NULL;
54 NetDevice *netDev = NULL;
55 struct wiphy *wiphy = NULL;
56 netDev = get_real_netdev(hnetDev);
57 enum nl80211_iftype old_iftype = 0;
58
59 netdev = GetLinuxInfByNetDevice(netDev);
60 if (!netdev) {
61 HDF_LOGE("%s: net_device is NULL", __func__);
62 return -1;
63 }
64
65 wiphy = get_linux_wiphy_ndev(netdev);
66 if (!wiphy) {
67 HDF_LOGE("%s: wiphy is NULL", __func__);
68 return -1;
69 }
70 old_iftype = netdev->ieee80211_ptr->iftype;
71
72 HDF_LOGE("%s: start... iftype=%d, oldiftype=%d", __func__, iftype, old_iftype);
73 if (old_iftype == NL80211_IFTYPE_AP && iftype != old_iftype) {
74 WalStopAp(netDev);
75 }
76
77 if (iftype == NL80211_IFTYPE_P2P_GO && old_iftype == NL80211_IFTYPE_P2P_GO) {
78 HDF_LOGE("%s: p2p go don't change mode", __func__);
79 return retVal;
80 }
81
82 retVal = (int32_t)wl_cfg80211_ops.change_virtual_intf(wiphy, netdev,
83 (enum nl80211_iftype)iftype, NULL);
84 if (retVal < 0) {
85 HDF_LOGE("%s: set mode failed!", __func__);
86 }
87
88 return retVal;
89 }
90
BDH6WalAddKey(struct NetDevice * hnetDev,uint8_t keyIndex,bool pairwise,const uint8_t * macAddr,struct KeyParams * params)91 int32_t BDH6WalAddKey(struct NetDevice *hnetDev, uint8_t keyIndex, bool pairwise, const uint8_t *macAddr,
92 struct KeyParams *params)
93 {
94 int32_t retVal = 0;
95 struct NetDevice *netDev = NULL;
96 struct net_device *netdev = NULL;
97 struct wiphy *wiphy = NULL;
98 netDev = get_real_netdev(hnetDev);
99
100 #if (LINUX_VERSION_CODE > KERNEL_VERSION(5, 10, 0))
101 struct key_params keypm;
102 #endif
103
104 netdev = GetLinuxInfByNetDevice(netDev);
105 if (!netdev) {
106 HDF_LOGE("%s: net_device is NULL", __func__);
107 return -1;
108 }
109
110 wiphy = get_linux_wiphy_ndev(netdev);
111 if (!wiphy) {
112 HDF_LOGE("%s: wiphy is NULL", __func__);
113 return -1;
114 }
115
116 HDF_LOGE("%s: start..., mac = %p, keyIndex = %u,pairwise = %d, cipher = 0x%x, seqlen = %d, keylen = %d",
117 __func__, macAddr, keyIndex, pairwise, params->cipher, params->seqLen, params->keyLen);
118 (void)netDev;
119 #if (LINUX_VERSION_CODE > KERNEL_VERSION(5, 10, 0))
120 memset_s(&keypm, sizeof(struct key_params), 0, sizeof(struct key_params));
121 keypm.key = params->key;
122 keypm.seq = params->seq;
123 keypm.key_len = params->keyLen;
124 keypm.seq_len = params->seqLen;
125 keypm.cipher = params->cipher;
126 keypm.vlan_id = 0;
127 retVal = (int32_t)wl_cfg80211_ops.add_key(wiphy, netdev, keyIndex, pairwise, macAddr, &keypm);
128 #else
129 retVal = (int32_t)wl_cfg80211_ops.add_key(wiphy, netdev, keyIndex, pairwise, macAddr, (struct key_params *)params);
130 #endif
131 if (retVal < 0) {
132 HDF_LOGE("%s: add key failed!", __func__);
133 }
134
135 return retVal;
136 }
137
BDH6WalDelKey(struct NetDevice * hnetDev,uint8_t keyIndex,bool pairwise,const uint8_t * macAddr)138 int32_t BDH6WalDelKey(struct NetDevice *hnetDev, uint8_t keyIndex, bool pairwise, const uint8_t *macAddr)
139 {
140 int32_t retVal = 0;
141 struct NetDevice *netDev = NULL;
142 struct net_device *netdev = NULL;
143 struct wiphy *wiphy = NULL;
144 netDev = get_real_netdev(hnetDev);
145
146 netdev = GetLinuxInfByNetDevice(netDev);
147 if (!netdev) {
148 HDF_LOGE("%s: net_device is NULL", __func__);
149 return -1;
150 }
151
152 wiphy = get_linux_wiphy_ndev(netdev);
153 if (!wiphy) {
154 HDF_LOGE("%s: wiphy is NULL", __func__);
155 return -1;
156 }
157
158 HDF_LOGE("%s: start..., mac=%p, keyIndex=%u,pairwise=%d", __func__, macAddr, keyIndex, pairwise);
159
160 (void)netDev;
161 retVal = (int32_t)wl_cfg80211_ops.del_key(wiphy, netdev, keyIndex, pairwise, macAddr);
162 if (retVal < 0) {
163 HDF_LOGE("%s: delete key failed!", __func__);
164 }
165
166 return retVal;
167 }
168
BDH6WalSetDefaultKey(struct NetDevice * hnetDev,uint8_t keyIndex,bool unicast,bool multicas)169 int32_t BDH6WalSetDefaultKey(struct NetDevice *hnetDev, uint8_t keyIndex, bool unicast, bool multicas)
170 {
171 int32_t retVal = 0;
172 struct NetDevice *netDev = NULL;
173 struct net_device *netdev = NULL;
174 struct wiphy *wiphy = NULL;
175 netDev = get_real_netdev(hnetDev);
176
177 netdev = GetLinuxInfByNetDevice(netDev);
178 if (!netdev) {
179 HDF_LOGE("%s: net_device is NULL", __func__);
180 return -1;
181 }
182
183 wiphy = get_linux_wiphy_ndev(netdev);
184 if (!wiphy) {
185 HDF_LOGE("%s: wiphy is NULL", __func__);
186 return -1;
187 }
188 HDF_LOGE("%s: start..., keyIndex=%u,unicast=%d, multicas=%d", __func__, keyIndex, unicast, multicas);
189 retVal = (int32_t)wl_cfg80211_ops.set_default_key(wiphy, netdev, keyIndex, unicast, multicas);
190 if (retVal < 0) {
191 HDF_LOGE("%s: set default key failed!", __func__);
192 }
193
194 return retVal;
195 }
196
BDH6WalGetDeviceMacAddr(NetDevice * hnetDev,int32_t type,uint8_t * mac,uint8_t len)197 int32_t BDH6WalGetDeviceMacAddr(NetDevice *hnetDev, int32_t type, uint8_t *mac, uint8_t len)
198 {
199 struct NetDevice *netDev = NULL;
200 netDev = get_real_netdev(hnetDev);
201 struct net_device *netdev = GetLinuxInfByNetDevice(netDev);
202 if (!netdev) {
203 HDF_LOGE("%s: net_device is NULL", __func__);
204 return -1;
205 }
206
207 (void)len;
208 (void)type;
209 (void)netDev;
210 HDF_LOGE("%s: start...", __func__);
211
212 memcpy_s(mac, len, netdev->dev_addr, netdev->addr_len);
213
214 return HDF_SUCCESS;
215 }
216
BDH6WalSetMacAddr(NetDevice * hnetDev,uint8_t * mac,uint8_t len)217 int32_t BDH6WalSetMacAddr(NetDevice *hnetDev, uint8_t *mac, uint8_t len)
218 {
219 int32_t retVal = 0;
220 struct NetDevice *netDev = NULL;
221 struct sockaddr sa;
222 netDev = get_real_netdev(hnetDev);
223 struct net_device *netdev = GetLinuxInfByNetDevice(netDev);
224 if (!netdev) {
225 HDF_LOGE("%s: net_device is NULL", __func__);
226 return -1;
227 }
228
229 HDF_LOGE("%s: start...", __func__);
230 if (mac == NULL || len != ETH_ALEN) {
231 HDF_LOGE("%s: mac is error, len=%u", __func__, len);
232 return -1;
233 }
234 if (!is_valid_ether_addr(mac)) {
235 HDF_LOGE("%s: mac is invalid %02x:%02x:%02x:%02x:%02x:%02x", __func__,
236 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
237 return -1;
238 }
239
240 memcpy_s(sa.sa_data, ETH_ALEN, mac, len);
241
242 retVal = (int32_t)dhd_ops_pri.ndo_set_mac_address(netdev, (void *)&sa);
243 if (retVal < 0) {
244 HDF_LOGE("%s: set mac address failed!", __func__);
245 }
246
247 return retVal;
248 }
249
BDH6WalSetTxPower(NetDevice * hnetDev,int32_t power)250 int32_t BDH6WalSetTxPower(NetDevice *hnetDev, int32_t power)
251 {
252 int retVal = 0;
253 struct wiphy *wiphy = NULL;
254 struct NetDevice *netDev = NULL;
255 netDev = get_real_netdev(hnetDev);
256
257 // sync from net_device->ieee80211_ptr
258 struct wireless_dev *wdev = GET_NET_DEV_CFG80211_WIRELESS(netDev);
259
260 wiphy = get_linux_wiphy_hdfdev(netDev);
261 if (!wiphy) {
262 HDF_LOGE("%s: wiphy is NULL", __func__);
263 return -1;
264 }
265
266 HDF_LOGE("%s: start...", __func__);
267 retVal = (int32_t)wl_cfg80211_ops.set_tx_power(wiphy, wdev, NL80211_TX_POWER_FIXED, power);
268 if (retVal < 0) {
269 HDF_LOGE("%s: set_tx_power failed!", __func__);
270 }
271
272 return HDF_SUCCESS;
273 }
274
BDH6WalReleaseHwCapability(struct WlanHwCapability * self)275 void BDH6WalReleaseHwCapability(struct WlanHwCapability *self)
276 {
277 uint8_t i;
278 if (self == NULL) {
279 return;
280 }
281 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
282 if (self->bands[i] != NULL) {
283 OsalMemFree(self->bands[i]);
284 self->bands[i] = NULL;
285 }
286 }
287 if (self->supportedRates != NULL) {
288 OsalMemFree(self->supportedRates);
289 self->supportedRates = NULL;
290 }
291 OsalMemFree(self);
292 }
293
BDH6WalGetIftype(struct NetDevice * hnetDev,uint8_t * iftype)294 int32_t BDH6WalGetIftype(struct NetDevice *hnetDev, uint8_t *iftype)
295 {
296 struct NetDevice *netDev = NULL;
297 netDev = get_real_netdev(hnetDev);
298 iftype = (uint8_t *)(&(GET_NET_DEV_CFG80211_WIRELESS(netDev)->iftype));
299 HDF_LOGE("%s: start...", __func__);
300 return HDF_SUCCESS;
301 }
302
303 static struct HdfMac80211BaseOps g_bdh6_baseOps = {
304 .SetMode = BDH6WalSetMode,
305 .AddKey = BDH6WalAddKey,
306 .DelKey = BDH6WalDelKey,
307 .SetDefaultKey = BDH6WalSetDefaultKey,
308
309 .GetDeviceMacAddr = BDH6WalGetDeviceMacAddr,
310 .SetMacAddr = BDH6WalSetMacAddr,
311 .SetTxPower = BDH6WalSetTxPower,
312 .GetValidFreqsWithBand = Bdh6Fband,
313
314 .GetHwCapability = Bdh6Ghcap,
315 .SendAction = Bdh6SAction,
316 .GetIftype = BDH6WalGetIftype,
317
318 };
319
BDH6Mac80211Init(struct HdfChipDriver * chipDriver)320 void BDH6Mac80211Init(struct HdfChipDriver *chipDriver)
321 {
322 HDF_LOGE("%s: start...", __func__);
323
324 if (chipDriver == NULL) {
325 HDF_LOGE("%s: input is NULL", __func__);
326 return;
327 }
328
329 chipDriver->ops = &g_bdh6_baseOps;
330 chipDriver->staOps = &g_bdh6_staOps;
331 chipDriver->apOps = &g_bdh6_apOps;
332 chipDriver->p2pOps = &g_bdh6_p2pOps;
333 }
334
335