• 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/cfg80211.h>
10 #include <net/regulatory.h>
11 
12 
13 #include <typedefs.h>
14 #include <ethernet.h>
15 #include <bcmutils.h>
16 
17 #include <securec.h>
18 
19 #include "wifi_mac80211_ops.h"
20 #include "hdf_wlan_utils.h"
21 #include "wifi_module.h"
22 
23 #include "osal_mem.h"
24 #include "hdf_wifi_event.h"
25 #include "hdf_log.h"
26 
27 #include "net_device_adapter.h"
28 #include "hdf_public_ap6275s.h"
29 
30 #define HDF_LOG_TAG bcmdhd
31 
32 struct net_device *g_save_kernel_net = NULL;
33 
34 /*--------------------------------------------------------------------------------------------------*/
35 /* public */
36 /*--------------------------------------------------------------------------------------------------*/
37 #define MAX_NUM_OF_ASSOCIATED_DEV		64
38 #define WLC_GET_ASSOCLIST		159
39 
40 #define ETH_MAC_LEN 6
41 
42 typedef struct maclist {
43     uint32 count;			/**< number of MAC addresses */
44     struct ether_addr ea[1];	/**< variable length array of MAC addresses */
45 } maclist_t;
46 
ChangDelSta(struct net_device * dev,const uint8_t * macAddr,uint8_t addrLen)47 int ChangDelSta(struct net_device *dev, const uint8_t *macAddr, uint8_t addrLen)
48 {
49     int ret;
50     struct NetDevice *netDev = GetHdfNetDeviceByLinuxInf(dev);
51     ret = HdfWifiEventDelSta(netDev, macAddr, ETH_MAC_LEN);
52     return ret;
53 }
54 
ChangNewSta(struct net_device * dev,const uint8_t * macAddr,uint8_t addrLen,const struct station_info * info)55 int ChangNewSta(struct net_device *dev, const uint8_t *macAddr, uint8_t addrLen,
56     const struct station_info *info)
57 {
58     int ret;
59     struct NetDevice *netDev = NULL;
60     struct StationInfo Info = {0};
61 
62     Info.assocReqIes = info->assoc_req_ies;
63     Info.assocReqIesLen = info->assoc_req_ies_len;
64 
65     netDev = GetHdfNetDeviceByLinuxInf(dev);
66 
67     ret = HdfWifiEventNewSta(netDev, macAddr, addrLen, &Info);
68     return ret;
69 }
70 
71 
wl_get_all_sta(struct net_device * ndev,uint32_t * num)72 int32_t wl_get_all_sta(struct net_device *ndev, uint32_t *num)
73 {
74     int ret = 0;
75     char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV * sizeof(struct ether_addr) + sizeof(uint)] = {0};
76     struct maclist *assoc_maclist = (struct maclist *)mac_buf;
77     assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV;
78     ret = wldev_ioctl_get(ndev, WLC_GET_ASSOCLIST, assoc_maclist, sizeof(mac_buf));
79     *num = assoc_maclist->count;
80     return 0;
81 }
82 
83 #define MAX_NUM_OF_ASSOCLIST    64
84 #define CMD_ASSOC_CLIENTS "ASSOCLIST"
85 
wl_get_all_sta_info(struct net_device * ndev,char * mac,uint32_t num)86 int wl_get_all_sta_info(struct net_device *ndev, char* mac, uint32_t num)
87 {
88     int bytes_written = 0;
89     int  error = 0;
90     int len = 0;
91     int i;
92     char mac_buf[MAX_NUM_OF_ASSOCLIST *sizeof(struct ether_addr) + sizeof(uint)] = {0};
93     struct maclist *assoc_maclist = (struct maclist *)mac_buf;
94     assoc_maclist->count = (MAX_NUM_OF_ASSOCLIST);
95     error = wldev_ioctl_get(ndev, WLC_GET_ASSOCLIST, assoc_maclist, sizeof(mac_buf));
96     if (error) {
97         return -1;
98     }
99     assoc_maclist->count = assoc_maclist->count;
100         bytes_written = snprintf_s(mac, num, num, "%s listcount: %d Stations:",
101         CMD_ASSOC_CLIENTS, assoc_maclist->count);
102     for (i = 0; i < assoc_maclist->count; i++) {
103     len = snprintf_s(mac + bytes_written, num - bytes_written, num - bytes_written, " " MACDBG,
104         MAC2STRDBG(assoc_maclist->ea[i].octet));
105         /* A return value of '(total_len - bytes_written)' or more means that the
106          * output was truncated
107          */
108         if ((len > 0) && (len < (num - bytes_written))) {
109             bytes_written += len;
110         } else {
111             bytes_written = -1;
112             break;
113         }
114     }
115 
116     return bytes_written;
117 }
118 
119 
120 #if 1
121 
122 #define RATE_OFFSET  2
123 #define CAP_OFFSET  2
124 // Copy from nl80211_check_ap_rate_selectors() in nl80211.c
bdh6_nl80211_check_ap_rate_selectors(struct cfg80211_ap_settings * params,const u8 * rates)125 static void bdh6_nl80211_check_ap_rate_selectors(struct cfg80211_ap_settings *params, const u8 *rates)
126 {
127     int i;
128 
129     if (!rates)
130         return;
131 
132     for (i = 0; i < rates[1]; i++) {
133         if (rates[RATE_OFFSET + i] == BSS_MEMBERSHIP_SELECTOR_HT_PHY)
134             params->ht_required = true;
135         if (rates[RATE_OFFSET + i] == BSS_MEMBERSHIP_SELECTOR_VHT_PHY)
136             params->vht_required = true;
137     }
138 }
139 
140 
141 // Copy from nl80211_calculate_ap_params() in nl80211.c
bdh6_nl80211_calculate_ap_params(struct cfg80211_ap_settings * params)142 static void bdh6_nl80211_calculate_ap_params(struct cfg80211_ap_settings *params)
143 {
144     const struct cfg80211_beacon_data *bcn = &params->beacon;
145     size_t ies_len = bcn->tail_len;
146     const u8 *ies = bcn->tail;
147     const u8 *rates;
148     const u8 *cap;
149 
150     rates = cfg80211_find_ie(WLAN_EID_SUPP_RATES, ies, ies_len);
151     HDF_LOGE("lijg: find beacon tail WLAN_EID_SUPP_RATES=%p", rates);
152     bdh6_nl80211_check_ap_rate_selectors(params, rates);
153 
154     rates = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, ies, ies_len);
155     HDF_LOGE("lijg: find beacon tail WLAN_EID_EXT_SUPP_RATES=%p", rates);
156     bdh6_nl80211_check_ap_rate_selectors(params, rates);
157 
158     cap = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies, ies_len);
159     HDF_LOGE("lijg: find beacon tail WLAN_EID_HT_CAPABILITY=%p", cap);
160     if (cap && cap[1] >= sizeof(*params->ht_cap))
161         params->ht_cap = (void *)(cap + CAP_OFFSET);
162     cap = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, ies, ies_len);
163     HDF_LOGE("lijg: find beacon tail WLAN_EID_VHT_CAPABILITY=%p", cap);
164     if (cap && cap[1] >= sizeof(*params->vht_cap))
165         params->vht_cap = (void *)(cap + CAP_OFFSET);
166 }
167 
168 #endif
169 
170 
171 static struct ieee80211_channel g_ap_ieee80211_channel;
172 
173 static struct cfg80211_ap_settings g_ap_setting_info;
174 static u8 g_ap_ssid[IEEE80211_MAX_SSID_LEN];
175 static int start_ap_flag = 0;
176 
SetupWireLessDev(struct net_device * netDev,struct WlanAPConf * apSettings)177 static int32_t SetupWireLessDev(struct net_device *netDev, struct WlanAPConf *apSettings)
178 {
179     struct wireless_dev *wdev = NULL;
180     struct ieee80211_channel *chan = NULL;
181 
182     wdev = netDev->ieee80211_ptr;
183     if (wdev == NULL) {
184         HDF_LOGE("%s: wdev is null", __func__);
185         return -1;
186     }
187 
188     wdev->iftype = NL80211_IFTYPE_AP;
189     wdev->preset_chandef.width = (enum nl80211_channel_type)apSettings->width;
190     wdev->preset_chandef.center_freq1 = apSettings->centerFreq1;
191     wdev->preset_chandef.center_freq2 = apSettings->centerFreq2;
192 
193     chan = ieee80211_get_channel(wdev->wiphy, apSettings->centerFreq1);
194     if (chan) {
195         wdev->preset_chandef.chan = chan;
196         HDF_LOGE("%s: use valid channel %u", __func__, chan->center_freq);
197     } else if (wdev->preset_chandef.chan == NULL) {
198         wdev->preset_chandef.chan = &g_ap_ieee80211_channel;
199         wdev->preset_chandef.chan->hw_value = apSettings->channel;
200         wdev->preset_chandef.chan->band = apSettings->band; // IEEE80211_BAND_2GHZ;
201         wdev->preset_chandef.chan->center_freq = apSettings->centerFreq1;
202         HDF_LOGE("%s: fill new channel %u", __func__, wdev->preset_chandef.chan->center_freq);
203     }
204 
205     g_ap_setting_info.chandef = wdev->preset_chandef;
206 
207     return HDF_SUCCESS;
208 }
209 
210 /*--------------------------------------------------------------------------------------------------*/
211 /* HdfMac80211APOps */
212 /*--------------------------------------------------------------------------------------------------*/
WalConfigAp(NetDevice * netDev,struct WlanAPConf * apConf)213 int32_t WalConfigAp(NetDevice *netDev, struct WlanAPConf *apConf)
214 {
215     int32_t ret = 0;
216 
217     struct net_device *netdev = NULL;
218     struct wiphy *wiphy = NULL;
219     netdev = GetLinuxInfByNetDevice(netDev);
220     if (!netdev) {
221         HDF_LOGE("%s: net_device is NULL", __func__);
222         return -1;
223     }
224 
225     wiphy = get_linux_wiphy_ndev(netdev);
226     if (!wiphy) {
227         HDF_LOGE("%s: wiphy is NULL", __func__);
228         return -1;
229     }
230 
231     memset_s(&g_ap_setting_info, sizeof(g_ap_setting_info), 0x00, sizeof(g_ap_setting_info));
232     ret = SetupWireLessDev(netdev, apConf);
233     if (ret != 0) {
234         HDF_LOGE("%s: set up wireless device failed!", __func__);
235         return HDF_FAILURE;
236     }
237 
238     HDF_LOGE("%s: before iftype = %d!", __func__, netdev->ieee80211_ptr->iftype);
239     netdev->ieee80211_ptr->iftype = NL80211_IFTYPE_AP;
240     HDF_LOGE("%s: after  iftype = %d!", __func__, netdev->ieee80211_ptr->iftype);
241 
242     g_ap_setting_info.ssid_len = apConf->ssidConf.ssidLen;
243     memcpy_s(&g_ap_ssid[0], IEEE80211_MAX_SSID_LEN, &apConf->ssidConf.ssid[0], apConf->ssidConf.ssidLen);
244     g_ap_setting_info.ssid = &g_ap_ssid[0];
245 
246     ret = (int32_t)wl_cfg80211_ops.change_virtual_intf(wiphy, netdev,
247         (enum nl80211_iftype)netdev->ieee80211_ptr->iftype, NULL);
248     if (ret < 0) {
249         HDF_LOGE("%s: set mode failed!", __func__);
250     }
251 
252     return HDF_SUCCESS;
253 }
254 
WalSetCountryCode(NetDevice * netDev,const char * code,uint32_t len)255 int32_t WalSetCountryCode(NetDevice *netDev, const char *code, uint32_t len)
256 {
257     int32_t ret = 0;
258     struct net_device *netdev = NULL;
259     netdev = GetLinuxInfByNetDevice(netDev);
260     if (!netdev) {
261         HDF_LOGE("%s: net_device is NULL", __func__);
262         return -1;
263     }
264 
265     HDF_LOGE("%s: start...", __func__);
266     ret = (int32_t)wl_cfg80211_set_country_code(netdev, (char*)code, false, true, len);
267     if (ret < 0) {
268         HDF_LOGE("%s: set_country_code failed!", __func__);
269     }
270 
271     return ret;
272 }
273 
WalStopAp(NetDevice * netDev)274 int32_t WalStopAp(NetDevice *netDev)
275 {
276     int32_t ret = 0;
277     struct net_device *netdev = NULL;
278     struct wiphy *wiphy = NULL;
279     netdev = GetLinuxInfByNetDevice(netDev);
280     if (!netdev) {
281         HDF_LOGE("%s: net_device is NULL", __func__);
282         return -1;
283     }
284 
285     wiphy = get_linux_wiphy_ndev(netdev);
286     if (!wiphy) {
287         HDF_LOGE("%s: wiphy is NULL", __func__);
288         return -1;
289     }
290 
291     HDF_LOGE("%s: start...", __func__);
292     ret = (int32_t)wl_cfg80211_ops.stop_ap(wiphy, netdev);
293     return ret;
294 }
295 
WalStartAp(NetDevice * netDev)296 int32_t WalStartAp(NetDevice *netDev)
297 {
298     int32_t ret = 0;
299 
300     struct net_device *netdev = NULL;
301     struct wiphy *wiphy = NULL;
302     struct wireless_dev *wdev = NULL;
303 
304     if (start_ap_flag) {
305         WalStopAp(netDev);
306         HDF_LOGE("do not start up, because start_ap_flag=%d", start_ap_flag);
307     }
308 
309     netdev = GetLinuxInfByNetDevice(netDev);
310     if (!netdev) {
311         HDF_LOGE("%s: net_device is NULL", __func__);
312         return -1;
313     }
314 
315     wiphy = get_linux_wiphy_ndev(netdev);
316     if (!wiphy) {
317         HDF_LOGE("%s: wiphy is NULL", __func__);
318         return -1;
319     }
320     wdev = netdev->ieee80211_ptr;
321     ret = (int32_t)wl_cfg80211_ops.start_ap(wiphy, netdev, &g_ap_setting_info);
322     if (ret < 0) {
323         HDF_LOGE("%s: start_ap failed!", __func__);
324     } else {
325         wdev->preset_chandef = g_ap_setting_info.chandef;
326         wdev->beacon_interval = g_ap_setting_info.beacon_interval;
327         wdev->chandef = g_ap_setting_info.chandef;
328         wdev->ssid_len = g_ap_setting_info.ssid_len;
329         memcpy_s(wdev->ssid, IEEE80211_MAX_SSID_LEN, g_ap_setting_info.ssid, wdev->ssid_len);
330         start_ap_flag = 1;
331     }
332     return ret;
333 }
334 
335 
WalInitBeacon(struct WlanBeaconConf * param)336 static void WalInitBeacon(struct WlanBeaconConf *param)
337 {
338     if (g_ap_setting_info.beacon.head != NULL) {
339         OsalMemFree((uint8_t *)g_ap_setting_info.beacon.head);
340         g_ap_setting_info.beacon.head = NULL;
341     }
342     if (g_ap_setting_info.beacon.tail != NULL) {
343         OsalMemFree((uint8_t *)g_ap_setting_info.beacon.tail);
344         g_ap_setting_info.beacon.tail = NULL;
345     }
346 
347     if (param->headIEs && param->headIEsLength > 0) {
348         g_ap_setting_info.beacon.head = OsalMemCalloc(param->headIEsLength);
349         memcpy_s((uint8_t *)g_ap_setting_info.beacon.head, param->headIEsLength, param->headIEs, param->headIEsLength);
350         g_ap_setting_info.beacon.head_len = param->headIEsLength;
351     }
352 
353     if (param->tailIEs && param->tailIEsLength > 0) {
354         g_ap_setting_info.beacon.tail = OsalMemCalloc(param->tailIEsLength);
355         memcpy_s((uint8_t *)g_ap_setting_info.beacon.tail, param->tailIEsLength, param->tailIEs, param->tailIEsLength);
356         g_ap_setting_info.beacon.tail_len = param->tailIEsLength;
357     }
358 
359     g_ap_setting_info.dtim_period = param->DTIMPeriod;
360     g_ap_setting_info.hidden_ssid = param->hiddenSSID;
361     g_ap_setting_info.beacon_interval = param->interval;
362     g_ap_setting_info.beacon.beacon_ies = NULL;
363     g_ap_setting_info.beacon.proberesp_ies = NULL;
364     g_ap_setting_info.beacon.assocresp_ies = NULL;
365     g_ap_setting_info.beacon.probe_resp = NULL;
366 
367     g_ap_setting_info.beacon.beacon_ies_len = 0X00;
368     g_ap_setting_info.beacon.proberesp_ies_len = 0X00;
369     g_ap_setting_info.beacon.assocresp_ies_len = 0X00;
370     g_ap_setting_info.beacon.probe_resp_len = 0X00;
371 }
372 
WalChangeBeacon(NetDevice * netDev,struct WlanBeaconConf * param)373 int32_t WalChangeBeacon(NetDevice *netDev, struct WlanBeaconConf *param)
374 {
375     int32_t ret = 0;
376     struct cfg80211_beacon_data info;
377     struct net_device *netdev = NULL;
378     struct wiphy *wiphy = NULL;
379     netdev = GetLinuxInfByNetDevice(netDev);
380     if (!netdev) {
381         HDF_LOGE("%s: net_device is NULL", __func__);
382         return -1;
383     }
384 
385     wiphy = get_linux_wiphy_ndev(netdev);
386     if (!wiphy) {
387         HDF_LOGE("%s: wiphy is NULL", __func__);
388         return -1;
389     }
390     memset_s(&info, sizeof(info), 0x00, sizeof(info));
391 
392     WalInitBeacon(param);
393     info.head = param->headIEs;
394     info.head_len = (size_t)param->headIEsLength;
395     info.tail = param->tailIEs;
396     info.tail_len = (size_t)param->tailIEsLength;
397 
398     info.beacon_ies = NULL;
399     info.proberesp_ies = NULL;
400     info.assocresp_ies = NULL;
401     info.probe_resp = NULL;
402 
403     info.beacon_ies_len = 0X00;
404     info.proberesp_ies_len = 0X00;
405     info.assocresp_ies_len = 0X00;
406     info.probe_resp_len = 0X00;
407 
408     bdh6_nl80211_calculate_ap_params(&g_ap_setting_info);
409     ret = WalStartAp(netDev);
410     HDF_LOGE("call start_ap ret=%d", ret);
411 
412     ret = (int32_t)wl_cfg80211_ops.change_beacon(wiphy, netdev, &info);
413     if (ret < 0) {
414         HDF_LOGE("%s: change_beacon failed!", __func__);
415     }
416 
417     return HDF_SUCCESS;
418 }
419 
WalDelStation(NetDevice * netDev,const uint8_t * macAddr)420 int32_t WalDelStation(NetDevice *netDev, const uint8_t *macAddr)
421 {
422     int32_t ret = 0;
423     struct net_device *netdev = NULL;
424     struct wiphy *wiphy = NULL;
425     struct station_del_parameters del_param = {macAddr, 10, 0};
426     netdev = GetLinuxInfByNetDevice(netDev);
427     if (!netdev) {
428         HDF_LOGE("%s: net_device is NULL", __func__);
429         return -1;
430     }
431 
432     wiphy = get_linux_wiphy_ndev(netdev);
433     if (!wiphy) {
434         HDF_LOGE("%s: wiphy is NULL", __func__);
435         return -1;
436     }
437 
438     (void)macAddr;
439     HDF_LOGE("%s: start...", __func__);
440 
441     ret = (int32_t)wl_cfg80211_ops.del_station(wiphy, netdev, &del_param);
442     if (ret < 0) {
443         HDF_LOGE("%s: del_station failed!", __func__);
444     }
445 
446     return ret;
447 }
448 
WalGetAssociatedStasCount(NetDevice * netDev,uint32_t * num)449 int32_t WalGetAssociatedStasCount(NetDevice *netDev, uint32_t *num)
450 {
451     int32_t ret = 0;
452     struct net_device *netdev = NULL;
453     netdev = GetLinuxInfByNetDevice(netDev);
454     if (!netdev) {
455         HDF_LOGE("%s: net_device is NULL", __func__);
456         return -1;
457     }
458 
459     HDF_LOGE("%s: start...", __func__);
460 
461     ret = (int32_t)wl_get_all_sta(netdev, num);
462     if (ret < 0) {
463         HDF_LOGE("%s: wl_get_all_sta failed!", __func__);
464     }
465 
466     return ret;
467 }
468 
WalGetAssociatedStasInfo(NetDevice * netDev,WifiStaInfo * staInfo,uint32_t num)469 int32_t WalGetAssociatedStasInfo(NetDevice *netDev, WifiStaInfo *staInfo, uint32_t num)
470 {
471     int32_t ret = 0;
472     struct net_device *netdev = NULL;
473     netdev = GetLinuxInfByNetDevice(netDev);
474     if (!netdev) {
475         HDF_LOGE("%s: net_device is NULL", __func__);
476         return -1;
477     }
478 
479     HDF_LOGE("%s: start...", __func__);
480     ret = (int32_t)wl_get_all_sta_info(netdev, staInfo->mac, num);
481     if (ret < 0) {
482         HDF_LOGE("%s: wl_get_all_sta_info failed!", __func__);
483     }
484 
485     return ret;
486 }
487 /*--------------------------------------------------------------------------------------------------*/
488 /*--------------------------------------------------------------------------------------------------*/
489 /*--------------------------------------------------------------------------------------------------*/
490 
491 struct HdfMac80211APOps g_bdh6_apOps = {
492     .ConfigAp = WalConfigAp,
493     .StartAp = WalStartAp,
494     .StopAp = WalStopAp,
495     .ConfigBeacon = WalChangeBeacon,
496     .DelStation = WalDelStation,
497     .SetCountryCode = WalSetCountryCode,
498     .GetAssociatedStasCount = WalGetAssociatedStasCount,
499     .GetAssociatedStasInfo = WalGetAssociatedStasInfo
500 };
501