1 /*
2 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include <net/netlink.h>
10 #include <net/cfg80211.h>
11
12 #include <linux/kernel.h>
13 #include <linux/skbuff.h>
14 #include <linux/slab.h>
15 #include <linux/printk.h>
16 #include <linux/in6.h>
17 #include <linux/wireless.h>
18
19
20 #include <securec.h>
21
22 #include "osal_mem.h"
23
24 #include "net_device.h"
25 #include "net_device_impl.h"
26 #include "net_device_adapter.h"
27 #include "wifi_mac80211_ops.h"
28 #include "hdf_wifi_cmd.h"
29 #include "hdf_wifi_event.h"
30
31 #include "hdf_public_ap6275s.h"
32 #include "hdf_mac80211_sta.h"
33
34 #define HDF_LOG_TAG BDH6Driver
35
36
37 #define WIFI_SCAN_EXTRA_IE_LEN_MAX (512)
38
39 #define BDH6_POINT_CHANNEL_SIZE (8)
40
GetChannelByFreq(const struct wiphy * wiphy,uint16_t center_freq)41 static struct ieee80211_channel *GetChannelByFreq(const struct wiphy *wiphy, uint16_t center_freq)
42 {
43 enum Ieee80211Band band;
44 struct ieee80211_supported_band *currentBand = NULL;
45 int32_t loop;
46 for (band = (enum Ieee80211Band)0; band < IEEE80211_NUM_BANDS; band++) {
47 currentBand = wiphy->bands[band];
48 if (currentBand == NULL) {
49 continue;
50 }
51 for (loop = 0; loop < currentBand->n_channels; loop++) {
52 if (currentBand->channels[loop].center_freq == center_freq) {
53 return ¤tBand->channels[loop];
54 }
55 }
56 }
57 return NULL;
58 }
59
FillScanChannel(const struct wiphy * wiphy,int32_t channelTotal,enum Ieee80211Band band,struct cfg80211_scan_request * request)60 static int32_t FillScanChannel(const struct wiphy *wiphy, int32_t channelTotal,
61 enum Ieee80211Band band, struct cfg80211_scan_request *request)
62 {
63 int32_t loop;
64 int32_t count = 0;
65 struct ieee80211_channel *chan = NULL;
66
67 for (loop = 0; loop < (int32_t)wiphy->bands[band]->n_channels; loop++) {
68 if (count >= channelTotal) {
69 break;
70 }
71
72 chan = &wiphy->bands[band]->channels[loop];
73 if ((chan->flags & WIFI_CHAN_DISABLED) != 0) {
74 continue;
75 }
76
77 request->channels[count++] = chan;
78 }
79
80 return count;
81 }
82
83
WifiScanSetChannel(const struct wiphy * wiphy,const struct WlanScanRequest * params,struct cfg80211_scan_request * request)84 static int32_t WifiScanSetChannel(const struct wiphy *wiphy, const struct WlanScanRequest *params,
85 struct cfg80211_scan_request *request)
86 {
87 int32_t loop;
88 int32_t count = 0;
89 enum Ieee80211Band band = IEEE80211_BAND_2GHZ;
90 struct ieee80211_channel *chan = NULL;
91
92 int32_t channelTotal = ieee80211_get_num_supported_channels((struct wiphy *)wiphy);
93
94 if ((params->freqs == NULL) || (params->freqsCount == 0)) {
95 for (band = IEEE80211_BAND_2GHZ; band <= IEEE80211_BAND_5GHZ; band++) {
96 if (wiphy->bands[band] == NULL) {
97 HDF_LOGE("%s: wiphy->bands[band] = NULL!\n", __func__);
98 continue;
99 }
100
101 count = FillScanChannel(wiphy, channelTotal, band, request);
102 }
103 } else {
104 for (loop = 0; loop < params->freqsCount; loop++) {
105 chan = GetChannelByFreq(wiphy, (uint16_t)(params->freqs[loop]));
106 if (chan == NULL) {
107 HDF_LOGE("%s: freq not found!freq=%d!\n", __func__, params->freqs[loop]);
108 continue;
109 }
110
111 if (count >= channelTotal) {
112 break;
113 }
114
115 request->channels[count++] = chan;
116 }
117 }
118
119 if (count == 0) {
120 HDF_LOGE("%s: invalid freq info!\n", __func__);
121 return HDF_FAILURE;
122 }
123 request->n_channels = count;
124
125 return HDF_SUCCESS;
126 }
127
WifiScanSetSsid(const struct WlanScanRequest * params,struct cfg80211_scan_request * request)128 static int32_t WifiScanSetSsid(const struct WlanScanRequest *params, struct cfg80211_scan_request *request)
129 {
130 int32_t count = 0;
131 int32_t loop;
132
133 if (params->ssidCount > WPAS_MAX_SCAN_SSIDS) {
134 HDF_LOGE("%s:unexpected numSsids!numSsids=%u", __func__, params->ssidCount);
135 return HDF_FAILURE;
136 }
137
138 if (params->ssidCount == 0) {
139 HDF_LOGE("%s:ssid number is 0!", __func__);
140 return HDF_SUCCESS;
141 }
142
143 request->ssids = (struct cfg80211_ssid *)OsalMemCalloc(params->ssidCount * sizeof(struct cfg80211_ssid));
144 if (request->ssids == NULL) {
145 HDF_LOGE("%s: calloc request->ssids null", __func__);
146 return HDF_FAILURE;
147 }
148
149 for (loop = 0; loop < params->ssidCount; loop++) {
150 if (count >= DRIVER_MAX_SCAN_SSIDS) {
151 break;
152 }
153
154 if (params->ssids[loop].ssidLen > IEEE80211_MAX_SSID_LEN) {
155 continue;
156 }
157
158 request->ssids[count].ssid_len = params->ssids[loop].ssidLen;
159 if (memcpy_s(request->ssids[count].ssid, OAL_IEEE80211_MAX_SSID_LEN, params->ssids[loop].ssid,
160 params->ssids[loop].ssidLen) != EOK) {
161 continue;
162 }
163 count++;
164 }
165 request->n_ssids = count;
166
167 return HDF_SUCCESS;
168 }
169
WifiScanSetUserIe(const struct WlanScanRequest * params,struct cfg80211_scan_request * request)170 static int32_t WifiScanSetUserIe(const struct WlanScanRequest *params, struct cfg80211_scan_request *request)
171 {
172 if (params->extraIEsLen > WIFI_SCAN_EXTRA_IE_LEN_MAX) {
173 HDF_LOGE("%s:unexpected extra len!extraIesLen=%d", __func__, params->extraIEsLen);
174 return HDF_FAILURE;
175 }
176 if ((params->extraIEs != NULL) && (params->extraIEsLen != 0)) {
177 request->ie = (uint8_t *)OsalMemCalloc(params->extraIEsLen);
178 if (request->ie == NULL) {
179 HDF_LOGE("%s: calloc request->ie null", __func__);
180 return HDF_FAILURE;
181 }
182 (void)memcpy_s((void *)request->ie, params->extraIEsLen, params->extraIEs, params->extraIEsLen);
183 request->ie_len = params->extraIEsLen;
184 }
185
186 return HDF_SUCCESS;
187 }
188
WifiScanSetRequest(struct NetDevice * netdev,const struct WlanScanRequest * params,struct cfg80211_scan_request * request)189 static int32_t WifiScanSetRequest(struct NetDevice *netdev, const struct WlanScanRequest *params,
190 struct cfg80211_scan_request *request)
191 {
192 if (netdev == NULL || netdev->ieee80211Ptr == NULL) {
193 return HDF_FAILURE;
194 }
195 request->wiphy = GET_NET_DEV_CFG80211_WIRELESS(netdev)->wiphy;
196 request->wdev = GET_NET_DEV_CFG80211_WIRELESS(netdev);
197 request->n_ssids = params->ssidCount;
198 if (WifiScanSetChannel(GET_NET_DEV_CFG80211_WIRELESS(netdev)->wiphy, params, request)) {
199 HDF_LOGE("%s: set channel failed!", __func__);
200 return HDF_FAILURE;
201 }
202 if (WifiScanSetSsid(params, request)) {
203 HDF_LOGE("%s: set ssid failed!", __func__);
204 return HDF_FAILURE;
205 }
206 if (WifiScanSetUserIe(params, request)) {
207 HDF_LOGE("%s: set user ie failed!", __func__);
208 return HDF_FAILURE;
209 }
210 return HDF_SUCCESS;
211 }
212
WifiScanFree(struct cfg80211_scan_request ** request)213 static void WifiScanFree(struct cfg80211_scan_request **request)
214 {
215 HDF_LOGE("%s: enter... !", __func__);
216
217 if (*request != NULL) {
218 if ((*request)->ie != NULL) {
219 OsalMemFree((void *)(*request)->ie);
220 (*request)->ie = NULL;
221 }
222 if ((*request)->ssids != NULL) {
223 OsalMemFree((void *)(*request)->ssids);
224 (*request)->ssids = NULL;
225 }
226 OsalMemFree((void *)*request);
227 *request = NULL;
228 }
229 }
230
HdfStartScan(NetDevice * netDev,struct WlanScanRequest * scanParam)231 int32_t HdfStartScan(NetDevice *netDev, struct WlanScanRequest *scanParam)
232 {
233 int32_t ret = 0;
234
235 struct net_device *ndev = GetLinuxInfByNetDevice(netDev);
236 struct wiphy *wiphy = get_linux_wiphy_ndev(ndev);
237
238 int32_t channelTotal = ieee80211_get_num_supported_channels(wiphy);
239
240 struct cfg80211_scan_request *request =
241 (struct cfg80211_scan_request *)OsalMemCalloc(sizeof(struct cfg80211_scan_request) +
242 BDH6_POINT_CHANNEL_SIZE * channelTotal);
243
244 HDF_LOGE("%s: enter hdfStartScan, channelTotal: %d", __func__, channelTotal);
245
246 if (request == NULL) {
247 HDF_LOGE("%s: calloc request null!\n", __func__);
248 return HDF_FAILURE;
249 }
250 if (WifiScanSetRequest(netDev, scanParam, request) != HDF_SUCCESS) {
251 WifiScanFree(&request);
252 return HDF_FAILURE;
253 }
254
255 HDF_LOGE("%s: enter cfg80211_scan !", __func__);
256 ret = wl_cfg80211_ops.scan(wiphy, request);
257
258 HDF_LOGE("%s: left cfg80211_scan !", __func__);
259
260 if (ret != HDF_SUCCESS) {
261 WifiScanFree(&request);
262 }
263
264 return ret;
265 }
266
HdfAbortScan(NetDevice * netDev)267 int32_t HdfAbortScan(NetDevice *netDev)
268 {
269 struct net_device *ndev = NULL;
270 struct wireless_dev *wdev = NULL;
271 struct wiphy *wiphy = NULL;
272
273 if (netDev == NULL) {
274 HDF_LOGE("%s:NULL ptr!", __func__);
275 return HDF_FAILURE;
276 }
277
278 HDF_LOGE("%s: enter", __func__);
279
280 ndev = GetLinuxInfByNetDevice(netDev);
281
282 wiphy = get_linux_wiphy_ndev(ndev);
283
284 if (ndev == NULL) {
285 HDF_LOGE("%s:NULL ptr!", __func__);
286 return HDF_FAILURE;
287 }
288
289 wdev = ndev->ieee80211_ptr;
290
291 if (!wdev || !wdev->wiphy) {
292 return HDF_FAILURE;
293 }
294
295 wl_cfg80211_abort_scan(wiphy, wdev);
296
297 return HDF_SUCCESS;
298 }
299
WalGetChannel(struct wiphy * wiphy,int32_t freq)300 static struct ieee80211_channel *WalGetChannel(struct wiphy *wiphy, int32_t freq)
301 {
302 int32_t loop;
303
304 enum Ieee80211Band band = IEEE80211_BAND_2GHZ;
305 struct ieee80211_supported_band *currentBand = NULL;
306
307 if (wiphy == NULL) {
308 HDF_LOGE("%s: capality is NULL!", __func__);
309 return NULL;
310 }
311
312 for (band = (enum Ieee80211Band)0; band < IEEE80211_NUM_BANDS; band++) {
313 currentBand = wiphy->bands[band];
314 if (currentBand == NULL) {
315 continue;
316 }
317
318 for (loop = 0; loop < currentBand->n_channels; loop++) {
319 if (currentBand->channels[loop].center_freq == freq) {
320 return ¤tBand->channels[loop];
321 }
322 }
323 }
324
325 return NULL;
326 }
327
HdfFillConnParam(struct cfg80211_connect_params * cfg_param,WlanConnectParams * param)328 static void HdfFillConnParam(struct cfg80211_connect_params *cfg_param, WlanConnectParams *param)
329 {
330 cfg_param->bssid = param->bssid;
331 cfg_param->ssid = param->ssid;
332 cfg_param->ie = param->ie;
333 cfg_param->ssid_len = param->ssidLen;
334 cfg_param->ie_len = param->ieLen;
335
336 cfg_param->crypto.wpa_versions = param->crypto.wpaVersions;
337 cfg_param->crypto.cipher_group = param->crypto.cipherGroup;
338 cfg_param->crypto.n_ciphers_pairwise = param->crypto.n_ciphersPairwise;
339
340 memcpy_s(cfg_param->crypto.ciphers_pairwise,
341 NL80211_MAX_NR_CIPHER_SUITES*sizeof(cfg80211_params.crypto.ciphers_pairwise[0]),
342 param->crypto.ciphersPairwise, NL80211_MAX_NR_CIPHER_SUITES*sizeof(param->crypto.ciphersPairwise[0]));
343
344 memcpy_s(cfg_param->crypto.akm_suites,
345 NL80211_MAX_NR_AKM_SUITES*sizeof(cfg80211_params.crypto.akm_suites[0]),
346 param->crypto.akmSuites, NL80211_MAX_NR_AKM_SUITES*sizeof(param->crypto.akmSuites[0]));
347
348 cfg_param->crypto.n_akm_suites = param->crypto.n_akmSuites;
349
350 if (param->crypto.controlPort) {
351 cfg_param->crypto.control_port = true;
352 } else {
353 cfg_param->crypto.control_port = false;
354 }
355
356 cfg_param->crypto.control_port_ethertype = param->crypto.controlPortEthertype;
357 cfg_param->crypto.control_port_no_encrypt = param->crypto.controlPortNoEncrypt;
358
359 cfg_param->key = param->key;
360 cfg_param->auth_type = (unsigned char)param->authType;
361 cfg_param->privacy = param->privacy;
362 cfg_param->key_len = param->keyLen;
363 cfg_param->key_idx = param->keyIdx;
364 cfg_param->mfp = (unsigned char)param->mfp;
365 }
366
HdfConnect(NetDevice * netDev,WlanConnectParams * param)367 int32_t HdfConnect(NetDevice *netDev, WlanConnectParams *param)
368 {
369 int32_t ret = 0;
370 struct net_device *ndev = NULL;
371 struct wiphy *wiphy = NULL;
372 struct cfg80211_connect_params cfg80211_params = { 0 };
373
374 if (netDev == NULL || param == NULL) {
375 HDF_LOGE("%s:NULL ptr!", __func__);
376 return HDF_FAILURE;
377 }
378
379 ndev = GetLinuxInfByNetDevice(netDev);
380 if (ndev == NULL) {
381 HDF_LOGE("%s:NULL ptr!", __func__);
382 return HDF_FAILURE;
383 }
384
385 wiphy = get_linux_wiphy_ndev(ndev);
386 if (!wiphy) {
387 HDF_LOGE("%s: wiphy is NULL", __func__);
388 return -1;
389 }
390
391 if (param->centerFreq != WLAN_FREQ_NOT_SPECFIED) {
392 cfg80211_params.channel = WalGetChannel(wiphy, param->centerFreq);
393 if ((cfg80211_params.channel == NULL) || (cfg80211_params.channel->flags & WIFI_CHAN_DISABLED)) {
394 HDF_LOGE("%s:illegal channel.flags=%u", __func__,
395 (cfg80211_params.channel == NULL) ? 0 : cfg80211_params.channel->flags);
396 return HDF_FAILURE;
397 }
398 }
399
400 HdfFillConnParam(&cfg80211_params, param);
401 ret = wl_cfg80211_ops.connect(wiphy, ndev, &cfg80211_params);
402 if (ret < 0) {
403 HDF_LOGE("%s: connect failed!\n", __func__);
404 }
405
406 return ret;
407 }
408
HdfDisconnect(NetDevice * netDev,uint16_t reasonCode)409 int32_t HdfDisconnect(NetDevice *netDev, uint16_t reasonCode)
410 {
411 int32_t ret = 0;
412 struct net_device *ndev = NULL;
413 struct wiphy *wiphy = NULL;
414
415 HDF_LOGE("%s: start...", __func__);
416
417 if (netDev == NULL) {
418 HDF_LOGE("%s:NULL ptr!", __func__);
419 return HDF_FAILURE;
420 }
421 ndev = GetLinuxInfByNetDevice(netDev);
422 if (ndev == NULL) {
423 HDF_LOGE("%s:NULL ptr!", __func__);
424 return HDF_FAILURE;
425 }
426 wiphy = get_linux_wiphy_ndev(ndev);
427 if (!wiphy) {
428 HDF_LOGE("%s: wiphy is NULL", __func__);
429 return -1;
430 }
431 ret = wl_cfg80211_ops.disconnect(wiphy, ndev, reasonCode);
432 return ret;
433 }
434
HdfSetScanningMacAddress(NetDevice * netDev,unsigned char * mac,uint32_t len)435 int32_t HdfSetScanningMacAddress(NetDevice *netDev, unsigned char *mac, uint32_t len)
436 {
437 (void)netDev;
438 (void)mac;
439 (void)len;
440 return HDF_ERR_NOT_SUPPORT;
441 }
442
443 struct HdfMac80211STAOps g_bdh6_staOps = {
444 .Connect = HdfConnect,
445 .Disconnect = HdfDisconnect,
446 .StartScan = HdfStartScan,
447 .AbortScan = HdfAbortScan,
448 .SetScanningMacAddress = HdfSetScanningMacAddress,
449 };
450
451