• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &currentBand->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 &currentBand->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