• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
17  * USA.
18  */
19 
20 #include "hdf_log.h"
21 #include "hdf_wifi_event.h"
22 #include "hdf_wlan_utils.h"
23 #include "osal_mem.h"
24 #include "osl.h"
25 #include "wifi_mac80211_ops.h"
26 #include "wifi_module.h"
27 #include <net/cfg80211.h>
28 #include <net/regulatory.h>
29 
30 #include "eapol.h"
31 #include "hdf_wl_interface.h"
32 #include "net_device_adapter.h"
33 #include <bcmutils.h>
34 #include <ethernet.h>
35 #include <securec.h>
36 #include <typedefs.h>
37 #include <wl_cfgp2p.h>
38 
39 enum wl_management_type {
40     WL_BEACON = 0x1,
41     WL_PROBE_RESP = 0x2,
42     WL_ASSOC_RESP = 0x4
43 };
44 
45 #define HDF_LOG_TAG BDH6Driver
46 #define HISI_DRIVER_FLAGS_AP 0x00000040
47 #define HISI_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE 0x00000400
48 #define HISI_DRIVER_FLAGS_P2P_CONCURRENT 0x00000200
49 #define HISI_DRIVER_FLAGS_P2P_CAPABLE 0x00000800
50 #define WLAN_WPS_IE_MAX_SIZE 352
51 
52 #if defined(WL_CFG80211_P2P_DEV_IF)
53 #define ndev_to_cfg(ndev) ((ndev)->ieee80211_ptr)
54 #else
55 #define ndev_to_cfg(ndev) (ndev)
56 #endif
57 #ifndef ERRNO_T
58 #define ERRNO_T
59 typedef int errno_t;
60 #endif
61 extern struct net_device_ops dhd_ops_pri;
62 extern struct cfg80211_ops wl_cfg80211_ops;
63 extern struct hdf_inf_map g_hdf_infmap[HDF_INF_MAX];
64 extern int g_hdf_ifidx;
65 extern int g_event_ifidx;
66 
67 extern struct net_device *
68 GetLinuxInfByNetDevice(const struct NetDevice *netDevice);
69 extern struct wiphy *get_linux_wiphy_ndev(struct net_device *ndev);
70 extern struct wiphy *get_linux_wiphy_hdfdev(NetDevice *netDev);
71 int BDH6InitNetdev(struct NetDevice *netDevice, int private_data_size, int type,
72                    int ifidx);
73 int get_dhd_priv_data_size(void);
74 struct NetDevice *get_hdf_netdev(int ifidx);
75 int get_scan_ifidx(const char *ifname);
76 
77 extern s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf,
78                                       int len, enum wl_management_type type);
79 
80 struct net_device *get_krn_netdev(int ifidx);
81 struct NetDevice *get_real_netdev(NetDevice *netDev);
82 extern void rtnl_lock(void);
83 extern void rtnl_unlock(void);
84 
85 static u64 p2p_cookie = 0;
86 int start_p2p_completed = 0;
87 
WalRemainOnChannel(struct NetDevice * netDev,WifiOnChannel * onChannel)88 int32_t WalRemainOnChannel(struct NetDevice *netDev, WifiOnChannel *onChannel)
89 {
90     struct net_device *netdev = NULL;
91     struct wiphy *wiphy = NULL;
92     bcm_struct_cfgdev *cfgdev = NULL;
93     struct ieee80211_channel *channel = NULL;
94     unsigned int duration;
95     struct NetDevice *hnetdev = netDev;
96     int ret = 0;
97 
98     netDev = get_real_netdev(netDev);
99     netdev = GetLinuxInfByNetDevice(netDev);
100     if (!netdev) {
101         HDF_LOGE("%s: net_device is NULL", __func__);
102         return -1;
103     }
104 
105     wiphy = get_linux_wiphy_ndev(netdev);
106     if (!wiphy) {
107         HDF_LOGE("%s: wiphy is NULL", __func__);
108         return -1;
109     }
110     HDF_LOGE("%s: ifname=%s, freq=%u, duration=%u", __func__, hnetdev->name,
111              onChannel->freq, onChannel->duration);
112 
113     channel = OsalMemCalloc(sizeof(struct ieee80211_channel));
114     cfgdev = ndev_to_cfg(netdev);
115     channel->center_freq = onChannel->freq; // remain_on_channel函数需要的参数
116     duration = (unsigned int)onChannel->duration;
117 
118     ret = wl_cfg80211_ops.remain_on_channel(wiphy, cfgdev, channel, duration,
119                                             &p2p_cookie);
120     OsalMemFree(channel);
121     return ret;
122 }
123 
WalCancelRemainOnChannel(struct NetDevice * netDev)124 int32_t WalCancelRemainOnChannel(struct NetDevice *netDev)
125 {
126     struct net_device *netdev = NULL;
127     bcm_struct_cfgdev *cfgdev = NULL;
128     struct wiphy *wiphy = NULL;
129     struct NetDevice *hnetdev = netDev;
130 
131     netDev = get_real_netdev(netDev);
132     netdev = GetLinuxInfByNetDevice(netDev);
133     wiphy = get_linux_wiphy_ndev(netdev);
134     if (!wiphy) {
135         HDF_LOGE("%s: wiphy is NULL", __func__);
136         return -1;
137     }
138 
139     HDF_LOGE("%s: ifname = %s", __func__, hnetdev->name);
140     if (!netdev) {
141         HDF_LOGE("%s: net_device is NULL", __func__);
142         return -1;
143     }
144 
145     cfgdev = ndev_to_cfg(netdev);
146 
147     return wl_cfg80211_ops.cancel_remain_on_channel(wiphy, cfgdev, p2p_cookie);
148 }
149 
WalProbeReqReport(struct NetDevice * netDev,int32_t report)150 int32_t WalProbeReqReport(struct NetDevice *netDev, int32_t report)
151 {
152     (void)report;
153     HDF_LOGE("%s: ifname = %s, report=%d", __func__, netDev->name, report);
154     return HDF_SUCCESS;
155 }
156 
WalAddIf(struct NetDevice * netDev,WifiIfAdd * ifAdd)157 int32_t WalAddIf(struct NetDevice *netDev, WifiIfAdd *ifAdd)
158 {
159     struct wiphy *wiphy = NULL;
160     struct wireless_dev *wdev = NULL;
161     int ret = 0;
162     struct net_device *p2p_netdev = NULL;
163     struct NetDevice *p2p_hnetdev = NULL;
164 
165     if (netDev == NULL || ifAdd == NULL) {
166         HDF_LOGE("%s:NULL ptr!", __func__);
167         return -1;
168     }
169 
170     HDF_LOGE("%s: ifname = %s, type=%u", __func__, netDev->name, ifAdd->type);
171     netDev = get_real_netdev(netDev);
172     if (g_hdf_infmap[HDF_INF_P2P1].hnetdev != NULL) {
173         HDF_LOGE("%s: ifidx=%d was used, failed add if", __func__,
174                  HDF_INF_P2P1);
175         return -1;
176     }
177 
178     ret = BDH6InitNetdev(netDev, get_dhd_priv_data_size(), ifAdd->type,
179                          HDF_INF_P2P1);
180     if (ret != 0) {
181         HDF_LOGE("%s:BDH6InitNetdev p2p-p2p0-0 failed", __func__);
182         return HDF_FAILURE;
183     }
184 
185     wiphy = get_linux_wiphy_hdfdev(netDev);
186     if (wiphy == NULL) {
187         HDF_LOGE("%s:get wlan0 wiphy failed", __func__);
188         return HDF_FAILURE;
189     }
190 
191     p2p_hnetdev = get_hdf_netdev(g_hdf_ifidx);
192     p2p_netdev = get_krn_netdev(g_hdf_ifidx);
193 
194     wdev = wl_cfg80211_ops.add_virtual_intf(wiphy, p2p_hnetdev->name,
195                                             NET_NAME_USER, ifAdd->type, NULL);
196     if (wdev == NULL || wdev == ERR_PTR(-ENODEV)) {
197         HDF_LOGE("%s:create wdev for %s %d failed", __func__, p2p_hnetdev->name,
198                  ifAdd->type);
199         return HDF_FAILURE;
200     }
201     HDF_LOGE("%s:%s wdev->netdev=%p, %p", __func__, p2p_hnetdev->name,
202              wdev->netdev, p2p_netdev);
203     p2p_hnetdev->ieee80211Ptr = p2p_netdev->ieee80211_ptr;
204 
205     // update mac addr to NetDevice object
206     memcpy_s(p2p_hnetdev->macAddr, MAC_ADDR_SIZE, p2p_netdev->dev_addr,
207              p2p_netdev->addr_len);
208     HDF_LOGE("%s: %s mac: %02x:%02x:%02x:%02x:%02x:%02x", __func__,
209              p2p_hnetdev->name, p2p_hnetdev->macAddr[0],
210              p2p_hnetdev->macAddr[1], p2p_hnetdev->macAddr[0x2],
211              p2p_hnetdev->macAddr[0x3], p2p_hnetdev->macAddr[0x4],
212              p2p_hnetdev->macAddr[0x5]);
213 
214     return HDF_SUCCESS;
215 }
216 
WalRemoveIf(struct NetDevice * netDev,WifiIfRemove * ifRemove)217 int32_t WalRemoveIf(struct NetDevice *netDev, WifiIfRemove *ifRemove)
218 {
219     int i = HDF_INF_WLAN0;
220     struct wiphy *wiphy = NULL;
221     struct wireless_dev *wdev = NULL;
222     struct NetDevice *p2p_hnetdev = NULL;
223     int ret = 0;
224     struct NetDevice *hnetdev = netDev;
225     netDev = get_real_netdev(netDev);
226 
227     wiphy = get_linux_wiphy_hdfdev(netDev);
228     if (wiphy == NULL) {
229         HDF_LOGE("%s:get wlan0 wiphy failed", __func__);
230         return HDF_FAILURE;
231     }
232 
233     HDF_LOGE("%s: ifname=%s, primary netdev %s, remove ifname=%s", __func__,
234              hnetdev->name, netDev->name, ifRemove->ifName);
235     for (; i < HDF_INF_MAX; i++) {
236         p2p_hnetdev = g_hdf_infmap[i].hnetdev;
237         if (p2p_hnetdev == NULL) {
238             continue;
239         }
240 
241         if (strcmp(p2p_hnetdev->name, ifRemove->ifName) == 0) {
242             // check safely
243             if (i == HDF_INF_WLAN0) {
244                 HDF_LOGE("%s: don't remove master interface %s", __func__,
245                          ifRemove->ifName);
246                 continue;
247             }
248             if (i != HDF_INF_P2P1) {
249                 HDF_LOGE("%s: remove %s is not p2p interface (%d %d)", __func__,
250                          ifRemove->ifName, i, HDF_INF_P2P1);
251             }
252 
253             wdev = (struct wireless_dev *)p2p_hnetdev->ieee80211Ptr;
254             ret = (int32_t)wl_cfg80211_ops.change_virtual_intf(
255                 wiphy, g_hdf_infmap[i].netdev, NL80211_IFTYPE_STATION, NULL);
256             HDF_LOGE("%s: change %s mode %d --> %d, ret=%d", __func__,
257                      g_hdf_infmap[i].netdev->name, wdev->iftype,
258                      NL80211_IFTYPE_STATION, ret);
259 
260             rtnl_lock();
261             // clear private object
262             DestroyEapolData(p2p_hnetdev);
263             p2p_hnetdev->ieee80211Ptr = NULL;
264             // This func free wdev object and call unregister_netdevice() and
265             // NetDeviceDeInit()
266             ret = wl_cfg80211_ops.del_virtual_intf(wiphy, wdev);
267 
268             g_hdf_infmap[i].hnetdev = NULL;
269             g_hdf_infmap[i].netdev = NULL;
270             g_hdf_infmap[i].wdev = NULL;
271             g_hdf_ifidx = HDF_INF_WLAN0;
272             g_event_ifidx = HDF_INF_P2P0;
273             rtnl_unlock();
274             break;
275         }
276     }
277 
278     return ret;
279 }
280 
WalSetApWpsP2pIe(struct NetDevice * netDev,WifiAppIe * appIe)281 int32_t WalSetApWpsP2pIe(struct NetDevice *netDev, WifiAppIe *appIe)
282 {
283     struct net_device *netdev = NULL;
284     enum wl_management_type type;
285 
286     netDev = get_real_netdev(netDev);
287     netdev = GetLinuxInfByNetDevice(netDev);
288     type = appIe->appIeType;
289 
290     HDF_LOGE("%s: primary netdev %s, type=%d", __func__, netDev->name, type);
291     if (!netdev) {
292         HDF_LOGE("%s: net_device is NULL", __func__);
293         return -1;
294     }
295 
296     if (appIe->ieLen > WLAN_WPS_IE_MAX_SIZE) {
297         return -1;
298     }
299 
300     return wl_cfg80211_set_wps_p2p_ie(netdev, appIe->ie, appIe->ieLen, type);
301 }
302 
303 void cfg80211_init_wdev(struct wireless_dev *wdev);
304 
hdf_start_p2p_device(void)305 int hdf_start_p2p_device(void)
306 {
307     int ret = HDF_SUCCESS;
308     struct wiphy *wiphy = NULL;
309     struct wireless_dev *wdev = NULL;
310     struct net_device *netdev = get_krn_netdev(HDF_INF_WLAN0);
311 
312     if (start_p2p_completed == 1) {
313         HDF_LOGE("%s:start p2p completed already", __func__);
314         return 0;
315     }
316 
317     // create wdev object for p2p-dev-wlan0 device, refer
318     // nl80211_new_interface()
319     wiphy = get_linux_wiphy_ndev(netdev);
320     if (wiphy == NULL) {
321         HDF_LOGE("%s:get wlan0 wiphy failed", __func__);
322         return HDF_FAILURE;
323     }
324 
325     wdev = wl_cfg80211_ops.add_virtual_intf(
326         wiphy, "p2p-dev-wlan0", NET_NAME_USER, NL80211_IFTYPE_P2P_DEVICE, NULL);
327     if (wdev == NULL) {
328         HDF_LOGE("%s:create wdev for p2p-dev-wlan0 %d failed", __func__,
329                  NL80211_IFTYPE_P2P_DEVICE);
330         return HDF_FAILURE;
331     }
332     cfg80211_init_wdev(wdev);
333     HDF_LOGE("%s:p2p-dev-wlan0 wdev->netdev=%p", __func__, wdev->netdev);
334 
335     g_hdf_infmap[HDF_INF_P2P0].wdev = wdev; // free it for module released !!
336 
337     ret = wl_cfg80211_ops.start_p2p_device(wiphy, NULL);
338     HDF_LOGE("call start_p2p_device ret = %d", ret);
339     g_event_ifidx = HDF_INF_P2P0;
340     start_p2p_completed = 1;
341 
342     return ret;
343 }
344 
WalGetDriverFlag(struct NetDevice * netDev,WifiGetDrvFlags ** params)345 int32_t WalGetDriverFlag(struct NetDevice *netDev, WifiGetDrvFlags **params)
346 {
347     struct wireless_dev *wdev = NULL;
348     WifiGetDrvFlags *getDrvFlag = NULL;
349     int iftype = 0;
350     int ifidx = 0;
351 
352     HDF_LOGE("%s: primary netdev %s", __func__, netDev->name);
353     if (netDev == NULL || params == NULL) {
354         HDF_LOGE("%s:NULL ptr!", __func__);
355         return -1;
356     }
357     wdev = (struct wireless_dev *)((netDev)->ieee80211Ptr);
358     getDrvFlag = (WifiGetDrvFlags *)OsalMemCalloc(sizeof(WifiGetDrvFlags));
359     if (wdev) {
360         iftype = wdev->iftype;
361     } else {
362         ifidx = get_scan_ifidx(netDev->name);
363         if (ifidx == HDF_INF_P2P0) {
364             iftype = NL80211_IFTYPE_P2P_DEVICE;
365         }
366     }
367 
368     switch (iftype) {
369         case NL80211_IFTYPE_P2P_CLIENT:
370             /* fall-through */
371         case NL80211_IFTYPE_P2P_GO:
372             getDrvFlag->drvFlags = (unsigned int)(HISI_DRIVER_FLAGS_AP);
373             g_event_ifidx = HDF_INF_P2P1;
374             break;
375         case NL80211_IFTYPE_P2P_DEVICE:
376             getDrvFlag->drvFlags =
377                 (unsigned int)(HISI_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE |
378                                HISI_DRIVER_FLAGS_P2P_CONCURRENT |
379                                HISI_DRIVER_FLAGS_P2P_CAPABLE);
380             hdf_start_p2p_device();
381             break;
382         default:
383             getDrvFlag->drvFlags = 0;
384     }
385 
386     *params = getDrvFlag;
387 
388     HDF_LOGE("%s: %s iftype=%d, drvflag=%lu", __func__, netDev->name, iftype,
389              getDrvFlag->drvFlags);
390     return HDF_SUCCESS;
391 }
392 
393 struct HdfMac80211P2POps g_bdh6_p2pOps = {
394     .RemainOnChannel = WalRemainOnChannel,
395     .CancelRemainOnChannel = WalCancelRemainOnChannel,
396     .ProbeReqReport = WalProbeReqReport,
397     .AddIf = WalAddIf,
398     .RemoveIf = WalRemoveIf,
399     .SetApWpsP2pIe = WalSetApWpsP2pIe,
400     .GetDriverFlag = WalGetDriverFlag,
401 };
402