• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Linux cfgp2p driver
4  *
5  * Copyright (C) 1999-2019, Broadcom.
6  *
7  *      Unless you and Broadcom execute a separate written software license
8  * agreement governing use of this software, this software is licensed to you
9  * under the terms of the GNU General Public License version 2 (the "GPL"),
10  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
11  * following added to such license:
12  *
13  *      As a special exception, the copyright holders of this software give you
14  * permission to link this software with independent modules, and to copy and
15  * distribute the resulting executable under terms of your choice, provided that
16  * you also meet, for each linked independent module, the terms and conditions of
17  * the license of that module.  An independent module is a module which is not
18  * derived from this software.  The special exception does not apply to any
19  * modifications of the software.
20  *
21  *      Notwithstanding the above, under no circumstances may you combine this
22  * software in any way with any other Broadcom software provided under a license
23  * other than the GPL, without Broadcom's express prior written consent.
24  *
25  *
26  * <<Broadcom-WL-IPTag/Open:>>
27  *
28  * $Id: wl_cfgp2p.c 819430 2019-05-13 11:38:06Z $
29  *
30  */
31 #include <typedefs.h>
32 #include <linuxver.h>
33 #include <osl.h>
34 #include <linux/kernel.h>
35 #include <linux/kthread.h>
36 #include <linux/netdevice.h>
37 #include <linux/etherdevice.h>
38 #include <linux/types.h>
39 #include <linux/string.h>
40 #include <linux/timer.h>
41 #include <linux/if_arp.h>
42 #include <linux/uaccess.h>
43 
44 #include <bcmutils.h>
45 #include <bcmstdlib_s.h>
46 #include <bcmendian.h>
47 #include <ethernet.h>
48 #include <802.11.h>
49 #include <net/rtnetlink.h>
50 
51 #include <wl_cfg80211.h>
52 #include <wl_cfgp2p.h>
53 #include <wl_cfgscan.h>
54 #include <wldev_common.h>
55 #include <wl_android.h>
56 #include <dngl_stats.h>
57 #include <dhd.h>
58 #include <dhd_linux.h>
59 #include <dhdioctl.h>
60 #include <wlioctl.h>
61 #include <dhd_cfg80211.h>
62 #include <dhd_bus.h>
63 #include <dhd_config.h>
64 
65 static s8 scanparambuf[WLC_IOCTL_SMLEN];
66 static bool wl_cfgp2p_has_ie(const bcm_tlv_t *ie, const u8 **tlvs, u32 *tlvs_len,
67                              const u8 *oui, u32 oui_len, u8 type);
68 
69 static s32 wl_cfgp2p_cancel_listen(struct bcm_cfg80211 *cfg, struct net_device *ndev,
70 	struct wireless_dev *wdev, bool notify);
71 
72 #if defined(WL_ENABLE_P2P_IF)
73 static netdev_tx_t wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev);
74 static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd);
75 static int wl_cfgp2p_if_open(struct net_device *net);
76 static int wl_cfgp2p_if_stop(struct net_device *net);
77 
78 static const struct net_device_ops wl_cfgp2p_if_ops = {
79 	.ndo_open       = wl_cfgp2p_if_open,
80 	.ndo_stop       = wl_cfgp2p_if_stop,
81 	.ndo_do_ioctl   = wl_cfgp2p_do_ioctl,
82 	.ndo_start_xmit = wl_cfgp2p_start_xmit,
83 };
84 #endif /* WL_ENABLE_P2P_IF */
85 
86 #ifdef CONFIG_AP6XXX_WIFI6_HDF
87 #include "net_device.h"
88 
89 extern int g_event_ifidx;
90 struct NetDevice * get_hdf_netdev(int ifidx);
91 int32_t HdfWifiEventCancelRemainOnChannel(const struct NetDevice *netDev, uint32_t freq);
92 #else
93 int dhd_del_monitor(struct net_device *ndev);
94 int magiclink_add_p2p(const char *name, struct ether_addr *p2p_dev_addr, struct net_device **new_ndev);
95 struct net_device* p2p_debug_ndev = NULL;
96 #endif
97 
wl_cfgp2p_is_pub_action(void * frame,u32 frame_len)98 bool wl_cfgp2p_is_pub_action(void *frame, u32 frame_len)
99 {
100 	wifi_p2p_pub_act_frame_t *pact_frm;
101 
102 	if (frame == NULL)
103 		return false;
104 	pact_frm = (wifi_p2p_pub_act_frame_t *)frame;
105 	if (frame_len < sizeof(wifi_p2p_pub_act_frame_t) -1)
106 		return false;
107 
108 	if (pact_frm->category == P2P_PUB_AF_CATEGORY &&
109 		pact_frm->action == P2P_PUB_AF_ACTION &&
110 		pact_frm->oui_type == P2P_VER &&
111 		memcmp(pact_frm->oui, P2P_OUI, sizeof(pact_frm->oui)) == 0) {
112 		return true;
113 	}
114 
115 	return false;
116 }
117 
wl_cfgp2p_is_p2p_action(void * frame,u32 frame_len)118 bool wl_cfgp2p_is_p2p_action(void *frame, u32 frame_len)
119 {
120 	wifi_p2p_action_frame_t *act_frm;
121 
122 	if (frame == NULL)
123 		return false;
124 	act_frm = (wifi_p2p_action_frame_t *)frame;
125 	if (frame_len < sizeof(wifi_p2p_action_frame_t) -1)
126 		return false;
127 
128 	if (act_frm->category == P2P_AF_CATEGORY &&
129 		act_frm->type  == P2P_VER &&
130 		memcmp(act_frm->OUI, P2P_OUI, DOT11_OUI_LEN) == 0) {
131 		return true;
132 	}
133 
134 	return false;
135 }
136 
137 #define GAS_RESP_LEN		2
138 #define DOUBLE_TLV_BODY_OFF	4
139 #define GAS_RESP_OFFSET		4
140 #define GAS_CRESP_OFFSET	5
141 
wl_cfgp2p_find_gas_subtype(u8 subtype,u8 * data,u32 len)142 bool wl_cfgp2p_find_gas_subtype(u8 subtype, u8* data, u32 len)
143 {
144 	const bcm_tlv_t *ie = (bcm_tlv_t *)data;
145 	const u8 *frame = NULL;
146 	u16 id, flen;
147 
148 	/* Skipped first ANQP Element, if frame has anqp elemnt */
149 	ie = bcm_parse_tlvs(ie, len, DOT11_MNG_ADVERTISEMENT_ID);
150 
151 	if (ie == NULL)
152 		return false;
153 
154 	frame = (const uint8 *)ie + ie->len + TLV_HDR_LEN + GAS_RESP_LEN;
155 	id = ((u16) (((frame)[1] << 8) | (frame)[0]));
156 	flen = ((u16) (((frame)[3] << 8) | (frame)[2]));
157 
158 	/* If the contents match the OUI and the type */
159 	if (flen >= WFA_OUI_LEN + 1 &&
160 		id ==  P2PSD_GAS_NQP_INFOID &&
161 		!bcmp(&frame[DOUBLE_TLV_BODY_OFF], (const uint8*)WFA_OUI, WFA_OUI_LEN) &&
162 		subtype == frame[DOUBLE_TLV_BODY_OFF+WFA_OUI_LEN]) {
163 		return true;
164 	}
165 
166 	return false;
167 }
168 
wl_cfgp2p_is_gas_action(void * frame,u32 frame_len)169 bool wl_cfgp2p_is_gas_action(void *frame, u32 frame_len)
170 {
171 
172 	wifi_p2psd_gas_pub_act_frame_t *sd_act_frm;
173 
174 	if (frame == NULL)
175 		return false;
176 
177 	sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)frame;
178 	if (frame_len < (sizeof(wifi_p2psd_gas_pub_act_frame_t) - 1))
179 		return false;
180 	if (sd_act_frm->category != P2PSD_ACTION_CATEGORY)
181 		return false;
182 
183 #ifdef WL11U
184 	if (sd_act_frm->action == P2PSD_ACTION_ID_GAS_IRESP)
185 		return wl_cfgp2p_find_gas_subtype(P2PSD_GAS_OUI_SUBTYPE,
186 			(u8 *)sd_act_frm->query_data + GAS_RESP_OFFSET,
187 			frame_len);
188 
189 	else if (sd_act_frm->action == P2PSD_ACTION_ID_GAS_CRESP)
190 		return wl_cfgp2p_find_gas_subtype(P2PSD_GAS_OUI_SUBTYPE,
191 			(u8 *)sd_act_frm->query_data + GAS_CRESP_OFFSET,
192 			frame_len);
193 	else if (sd_act_frm->action == P2PSD_ACTION_ID_GAS_IREQ ||
194 		sd_act_frm->action == P2PSD_ACTION_ID_GAS_CREQ)
195 		return true;
196 	else
197 		return false;
198 #else
199 	if (sd_act_frm->action == P2PSD_ACTION_ID_GAS_IREQ ||
200 		sd_act_frm->action == P2PSD_ACTION_ID_GAS_IRESP ||
201 		sd_act_frm->action == P2PSD_ACTION_ID_GAS_CREQ ||
202 		sd_act_frm->action == P2PSD_ACTION_ID_GAS_CRESP)
203 		return true;
204 	else
205 		return false;
206 #endif /* WL11U */
207 }
208 
wl_cfgp2p_is_p2p_gas_action(void * frame,u32 frame_len)209 bool wl_cfgp2p_is_p2p_gas_action(void *frame, u32 frame_len)
210 {
211 
212 	wifi_p2psd_gas_pub_act_frame_t *sd_act_frm;
213 
214 	if (frame == NULL)
215 		return false;
216 
217 	sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)frame;
218 	if (frame_len < (sizeof(wifi_p2psd_gas_pub_act_frame_t) - 1))
219 		return false;
220 	if (sd_act_frm->category != P2PSD_ACTION_CATEGORY)
221 		return false;
222 
223 	if (sd_act_frm->action == P2PSD_ACTION_ID_GAS_IREQ)
224 		return wl_cfgp2p_find_gas_subtype(P2PSD_GAS_OUI_SUBTYPE,
225 			(u8 *)sd_act_frm->query_data,
226 			frame_len);
227 	else
228 		return false;
229 }
230 
wl_cfgp2p_print_actframe(bool tx,void * frame,u32 frame_len,u32 channel)231 void wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len, u32 channel)
232 {
233 	wifi_p2p_pub_act_frame_t *pact_frm;
234 	wifi_p2p_action_frame_t *act_frm;
235 	wifi_p2psd_gas_pub_act_frame_t *sd_act_frm;
236 	if (!frame || frame_len <= 2)
237 		return;
238 
239 	if (wl_cfgp2p_is_pub_action(frame, frame_len)) {
240 		pact_frm = (wifi_p2p_pub_act_frame_t *)frame;
241 		switch (pact_frm->subtype) {
242 			case P2P_PAF_GON_REQ:
243 				CFGP2P_ACTION(("%s P2P Group Owner Negotiation Req Frame,"
244 					" channel=%d\n", (tx)? "TX": "RX", channel));
245 				break;
246 			case P2P_PAF_GON_RSP:
247 				CFGP2P_ACTION(("%s P2P Group Owner Negotiation Rsp Frame,"
248 					" channel=%d\n", (tx)? "TX": "RX", channel));
249 				break;
250 			case P2P_PAF_GON_CONF:
251 				CFGP2P_ACTION(("%s P2P Group Owner Negotiation Confirm Frame,"
252 					" channel=%d\n", (tx)? "TX": "RX", channel));
253 				break;
254 			case P2P_PAF_INVITE_REQ:
255 				CFGP2P_ACTION(("%s P2P Invitation Request  Frame,"
256 					" channel=%d\n", (tx)? "TX": "RX", channel));
257 				break;
258 			case P2P_PAF_INVITE_RSP:
259 				CFGP2P_ACTION(("%s P2P Invitation Response Frame,"
260 					" channel=%d\n", (tx)? "TX": "RX", channel));
261 				break;
262 			case P2P_PAF_DEVDIS_REQ:
263 				CFGP2P_ACTION(("%s P2P Device Discoverability Request Frame,"
264 					" channel=%d\n", (tx)? "TX": "RX", channel));
265 				break;
266 			case P2P_PAF_DEVDIS_RSP:
267 				CFGP2P_ACTION(("%s P2P Device Discoverability Response Frame,"
268 					" channel=%d\n", (tx)? "TX": "RX", channel));
269 				break;
270 			case P2P_PAF_PROVDIS_REQ:
271 				CFGP2P_ACTION(("%s P2P Provision Discovery Request Frame,"
272 					" channel=%d\n", (tx)? "TX": "RX", channel));
273 				break;
274 			case P2P_PAF_PROVDIS_RSP:
275 				CFGP2P_ACTION(("%s P2P Provision Discovery Response Frame,"
276 					" channel=%d\n", (tx)? "TX": "RX", channel));
277 				break;
278 			default:
279 				CFGP2P_ACTION(("%s Unknown Public Action Frame,"
280 					" channel=%d\n", (tx)? "TX": "RX", channel));
281 
282 		}
283 
284 	} else if (wl_cfgp2p_is_p2p_action(frame, frame_len)) {
285 		act_frm = (wifi_p2p_action_frame_t *)frame;
286 		switch (act_frm->subtype) {
287 			case P2P_AF_NOTICE_OF_ABSENCE:
288 				CFGP2P_ACTION(("%s P2P Notice of Absence Frame,"
289 					" channel=%d\n", (tx)? "TX": "RX", channel));
290 				break;
291 			case P2P_AF_PRESENCE_REQ:
292 				CFGP2P_ACTION(("%s P2P Presence Request Frame,"
293 					" channel=%d\n", (tx)? "TX": "RX", channel));
294 				break;
295 			case P2P_AF_PRESENCE_RSP:
296 				CFGP2P_ACTION(("%s P2P Presence Response Frame,"
297 					" channel=%d\n", (tx)? "TX": "RX", channel));
298 				break;
299 			case P2P_AF_GO_DISC_REQ:
300 				CFGP2P_ACTION(("%s P2P Discoverability Request Frame,"
301 					" channel=%d\n", (tx)? "TX": "RX", channel));
302 				break;
303 			default:
304 				CFGP2P_ACTION(("%s Unknown P2P Action Frame,"
305 					" channel=%d\n", (tx)? "TX": "RX", channel));
306 		}
307 
308 	} else if (wl_cfgp2p_is_gas_action(frame, frame_len)) {
309 		sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)frame;
310 		switch (sd_act_frm->action) {
311 			case P2PSD_ACTION_ID_GAS_IREQ:
312 				CFGP2P_ACTION(("%s GAS Initial Request,"
313 					" channel=%d\n", (tx)? "TX" : "RX", channel));
314 				break;
315 			case P2PSD_ACTION_ID_GAS_IRESP:
316 				CFGP2P_ACTION(("%s GAS Initial Response,"
317 					" channel=%d\n", (tx)? "TX" : "RX", channel));
318 				break;
319 			case P2PSD_ACTION_ID_GAS_CREQ:
320 				CFGP2P_ACTION(("%s GAS Comback Request,"
321 					" channel=%d\n", (tx)? "TX" : "RX", channel));
322 				break;
323 			case P2PSD_ACTION_ID_GAS_CRESP:
324 				CFGP2P_ACTION(("%s GAS Comback Response,"
325 					" channel=%d\n", (tx)? "TX" : "RX", channel));
326 				break;
327 			default:
328 				CFGP2P_ACTION(("%s Unknown GAS Frame,"
329 					" channel=%d\n", (tx)? "TX" : "RX", channel));
330 		}
331 
332 	}
333 }
334 
335 /*
336  *  Initialize variables related to P2P
337  *
338  */
339 s32
wl_cfgp2p_init_priv(struct bcm_cfg80211 * cfg)340 wl_cfgp2p_init_priv(struct bcm_cfg80211 *cfg)
341 {
342 #ifdef WL_P2P_USE_RANDMAC
343 	struct ether_addr primary_mac;
344 #endif /* WL_P2P_USE_RANDMAC */
345 	cfg->p2p = MALLOCZ(cfg->osh, sizeof(struct p2p_info));
346 	if (cfg->p2p == NULL) {
347 		CFGP2P_ERR(("struct p2p_info allocation failed\n"));
348 		return -ENOMEM;
349 	}
350 #ifdef WL_P2P_USE_RANDMAC
351 	get_primary_mac(cfg, &primary_mac);
352 	wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
353 #endif /* WL_P2P_USE_RANDMAC */
354 	wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY) = bcmcfg_to_prmry_ndev(cfg);
355 	wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_PRIMARY) = 0;
356 	wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) = NULL;
357 	wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = 0;
358 	wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION1) = NULL;
359 	wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION1) = -1;
360 	wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION2) = NULL;
361 	wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION2) = -1;
362 	return BCME_OK;
363 
364 }
365 /*
366  *  Deinitialize variables related to P2P
367  *
368  */
369 void
wl_cfgp2p_deinit_priv(struct bcm_cfg80211 * cfg)370 wl_cfgp2p_deinit_priv(struct bcm_cfg80211 *cfg)
371 {
372 	CFGP2P_INFO(("In\n"));
373 	if (cfg->p2p) {
374 		MFREE(cfg->osh, cfg->p2p, sizeof(struct p2p_info));
375 		cfg->p2p = NULL;
376 	}
377 	cfg->p2p_supported = 0;
378 }
379 /*
380  * Set P2P functions into firmware
381  */
382 s32
wl_cfgp2p_set_firm_p2p(struct bcm_cfg80211 * cfg)383 wl_cfgp2p_set_firm_p2p(struct bcm_cfg80211 *cfg)
384 {
385 	struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
386 	s32 ret = BCME_OK;
387 	s32 val = 0;
388 #ifdef WL_P2P_USE_RANDMAC
389 	struct ether_addr *p2p_dev_addr = wl_to_p2p_bss_macaddr(cfg, P2PAPI_BSSCFG_DEVICE);
390 #else
391 	struct ether_addr null_eth_addr = { { 0, 0, 0, 0, 0, 0 } };
392 	struct ether_addr *p2p_dev_addr = &null_eth_addr;
393 #endif // endif
394 	/* Do we have to check whether APSTA is enabled or not ? */
395 	ret = wldev_iovar_getint(ndev, "apsta", &val);
396 	if (ret < 0) {
397 		CFGP2P_ERR(("get apsta error %d\n", ret));
398 		return ret;
399 	}
400 	if (val == 0) {
401 		val = 1;
402 		ret = wldev_ioctl_set(ndev, WLC_DOWN, &val, sizeof(s32));
403 		if (ret < 0) {
404 			CFGP2P_ERR(("WLC_DOWN error %d\n", ret));
405 			return ret;
406 		}
407 
408 		ret = wldev_iovar_setint(ndev, "apsta", val);
409 		if (ret < 0) {
410 			/* return error and fail the initialization */
411 			CFGP2P_ERR(("wl apsta %d set error. ret: %d\n", val, ret));
412 			return ret;
413 		}
414 
415 		ret = wldev_ioctl_set(ndev, WLC_UP, &val, sizeof(s32));
416 		if (ret < 0) {
417 			CFGP2P_ERR(("WLC_UP error %d\n", ret));
418 			return ret;
419 		}
420 	}
421 
422 	/* In case of COB type, firmware has default mac address
423 	 * After Initializing firmware, we have to set current mac address to
424 	 * firmware for P2P device address
425 	 */
426 	ret = wldev_iovar_setbuf_bsscfg(ndev, "p2p_da_override", p2p_dev_addr,
427 		sizeof(*p2p_dev_addr), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, 0, &cfg->ioctl_buf_sync);
428 	if (ret && ret != BCME_UNSUPPORTED) {
429 		CFGP2P_ERR(("failed to update device address ret %d\n", ret));
430 	}
431 	return ret;
432 }
433 
wl_cfg_multip2p_operational(struct bcm_cfg80211 * cfg)434 int wl_cfg_multip2p_operational(struct bcm_cfg80211 *cfg)
435 {
436 	if (!cfg->p2p) {
437 		CFGP2P_DBG(("p2p not enabled! \n"));
438 		return false;
439 	}
440 
441 	if ((wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION1) != -1) &&
442 	    (wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION2) != -1))
443 		return true;
444 	else
445 		return false;
446 }
447 
448 /* Create a new P2P BSS.
449  * Parameters:
450  * @mac      : MAC address of the BSS to create
451  * @if_type  : interface type: WL_P2P_IF_GO or WL_P2P_IF_CLIENT
452  * @chspec   : chspec to use if creating a GO BSS.
453  * Returns 0 if success.
454  */
455 s32
wl_cfgp2p_ifadd(struct bcm_cfg80211 * cfg,struct ether_addr * mac,u8 if_type,chanspec_t chspec)456 wl_cfgp2p_ifadd(struct bcm_cfg80211 *cfg, struct ether_addr *mac, u8 if_type,
457             chanspec_t chspec)
458 {
459 	wl_p2p_if_t ifreq;
460 	s32 err;
461 	struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
462 
463 	ifreq.type = if_type;
464 	ifreq.chspec = chspec;
465 	memcpy(ifreq.addr.octet, mac->octet, sizeof(ifreq.addr.octet));
466 
467 	CFGP2P_ERR(("---cfg p2p_ifadd "MACDBG" %s %u\n",
468 		MAC2STRDBG(ifreq.addr.octet),
469 		(if_type == WL_P2P_IF_GO) ? "go" : "client",
470 	        (chspec & WL_CHANSPEC_CHAN_MASK) >> WL_CHANSPEC_CHAN_SHIFT));
471 
472 	err = wldev_iovar_setbuf(ndev, "p2p_ifadd", &ifreq, sizeof(ifreq),
473 		cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
474 	if (unlikely(err < 0)) {
475 		CFGP2P_ERR(("'cfg p2p_ifadd' error %d\n", err));
476 		return err;
477 	}
478 
479 	return err;
480 }
481 
482 /* Disable a P2P BSS.
483  * Parameters:
484  * @mac      : MAC address of the BSS to disable
485  * Returns 0 if success.
486  */
487 s32
wl_cfgp2p_ifdisable(struct bcm_cfg80211 * cfg,struct ether_addr * mac)488 wl_cfgp2p_ifdisable(struct bcm_cfg80211 *cfg, struct ether_addr *mac)
489 {
490 	s32 ret;
491 	struct net_device *netdev = bcmcfg_to_prmry_ndev(cfg);
492 
493 	CFGP2P_INFO(("------ cfg p2p_ifdis "MACDBG" dev->ifindex:%d \n",
494 		MAC2STRDBG(mac->octet), netdev->ifindex));
495 	ret = wldev_iovar_setbuf(netdev, "p2p_ifdis", mac, sizeof(*mac),
496 		cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
497 	if (unlikely(ret < 0)) {
498 		CFGP2P_ERR(("'cfg p2p_ifdis' error %d\n", ret));
499 	}
500 	return ret;
501 }
502 
503 /* Delete a P2P BSS.
504  * Parameters:
505  * @mac      : MAC address of the BSS to delete
506  * Returns 0 if success.
507  */
508 s32
wl_cfgp2p_ifdel(struct bcm_cfg80211 * cfg,struct ether_addr * mac)509 wl_cfgp2p_ifdel(struct bcm_cfg80211 *cfg, struct ether_addr *mac)
510 {
511 	s32 ret;
512 #ifdef WL_DISABLE_HE_P2P
513 	s32 bssidx = 0;
514 #endif /* WL_DISABLE_HE_P2P */
515 	struct net_device *netdev = bcmcfg_to_prmry_ndev(cfg);
516 
517 	CFGP2P_ERR(("------ cfg p2p_ifdel "MACDBG" dev->ifindex:%d\n",
518 	    MAC2STRDBG(mac->octet), netdev->ifindex));
519 	ret = wldev_iovar_setbuf(netdev, "p2p_ifdel", mac, sizeof(*mac),
520 		cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
521 	if (unlikely(ret < 0)) {
522 		CFGP2P_ERR(("'cfg p2p_ifdel' error %d\n", ret));
523 	}
524 #ifdef WL_DISABLE_HE_P2P
525 	if ((bssidx = wl_get_bssidx_by_wdev(cfg, netdev->ieee80211_ptr)) < 0) {
526 		WL_ERR(("Find index failed\n"));
527 		ret = BCME_ERROR;
528 		return ret;
529 	}
530 	WL_DBG(("Enabling back HE for P2P\n"));
531 	wl_cfg80211_set_he_mode(netdev, cfg, bssidx, WL_IF_TYPE_P2P_DISC, TRUE);
532 	if (ret < 0) {
533 		WL_ERR(("failed to set he features, error=%d\n", ret));
534 	}
535 #endif /* WL_DISABLE_HE_P2P */
536 
537 	return ret;
538 }
539 
540 /* Change a P2P Role.
541  * Parameters:
542  * @mac      : MAC address of the BSS to change a role
543  * Returns 0 if success.
544  */
545 s32
wl_cfgp2p_ifchange(struct bcm_cfg80211 * cfg,struct ether_addr * mac,u8 if_type,chanspec_t chspec,s32 conn_idx)546 wl_cfgp2p_ifchange(struct bcm_cfg80211 *cfg, struct ether_addr *mac, u8 if_type,
547             chanspec_t chspec, s32 conn_idx)
548 {
549 	wl_p2p_if_t ifreq;
550 	s32 err;
551 
552 	struct net_device *netdev =  wl_to_p2p_bss_ndev(cfg, conn_idx);
553 
554 	ifreq.type = if_type;
555 	ifreq.chspec = chspec;
556 	memcpy(ifreq.addr.octet, mac->octet, sizeof(ifreq.addr.octet));
557 
558 	CFGP2P_INFO(("---cfg p2p_ifchange "MACDBG" %s %u"
559 		" chanspec 0x%04x\n", MAC2STRDBG(ifreq.addr.octet),
560 		(if_type == WL_P2P_IF_GO) ? "go" : "client",
561 		(chspec & WL_CHANSPEC_CHAN_MASK) >> WL_CHANSPEC_CHAN_SHIFT,
562 		ifreq.chspec));
563 
564 	err = wldev_iovar_setbuf(netdev, "p2p_ifupd", &ifreq, sizeof(ifreq),
565 		cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
566 	if (unlikely(err < 0)) {
567 		CFGP2P_ERR(("'cfg p2p_ifupd' error %d\n", err));
568 	} else if (if_type == WL_P2P_IF_GO) {
569 		cfg->p2p->p2p_go_count++;
570 	}
571 	return err;
572 }
573 
574 /* Get the index of a created P2P BSS.
575  * Parameters:
576  * @mac      : MAC address of the created BSS
577  * @index    : output: index of created BSS
578  * Returns 0 if success.
579  */
580 s32
wl_cfgp2p_ifidx(struct bcm_cfg80211 * cfg,struct ether_addr * mac,s32 * index)581 wl_cfgp2p_ifidx(struct bcm_cfg80211 *cfg, struct ether_addr *mac, s32 *index)
582 {
583 	s32 ret;
584 	u8 getbuf[64];
585 	struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
586 
587 	CFGP2P_INFO(("---cfg p2p_if "MACDBG"\n", MAC2STRDBG(mac->octet)));
588 
589 	ret = wldev_iovar_getbuf_bsscfg(dev, "p2p_if", mac, sizeof(*mac), getbuf,
590 		sizeof(getbuf), wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_PRIMARY), NULL);
591 
592 	if (ret == 0) {
593 		memcpy(index, getbuf, sizeof(s32));
594 		CFGP2P_DBG(("---cfg p2p_if   ==> %d\n", *index));
595 	}
596 
597 	return ret;
598 }
599 
600 static s32
wl_cfgp2p_set_discovery(struct bcm_cfg80211 * cfg,s32 on)601 wl_cfgp2p_set_discovery(struct bcm_cfg80211 *cfg, s32 on)
602 {
603 	s32 ret = BCME_OK;
604 	struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
605 	CFGP2P_DBG(("enter\n"));
606 
607 	ret = wldev_iovar_setint(ndev, "p2p_disc", on);
608 
609 	if (unlikely(ret < 0)) {
610 		CFGP2P_ERR(("p2p_disc %d error %d\n", on, ret));
611 	}
612 
613 	return ret;
614 }
615 
616 /* Set the WL driver's P2P mode.
617  * Parameters :
618  * @mode      : is one of WL_P2P_DISC_ST_{SCAN,LISTEN,SEARCH}.
619  * @channel   : the channel to listen
620  * @listen_ms : the time (milli seconds) to wait
621  * @bssidx    : bss index for BSSCFG
622  * Returns 0 if success
623  */
624 
625 s32
wl_cfgp2p_set_p2p_mode(struct bcm_cfg80211 * cfg,u8 mode,u32 channel,u16 listen_ms,int bssidx)626 wl_cfgp2p_set_p2p_mode(struct bcm_cfg80211 *cfg, u8 mode, u32 channel, u16 listen_ms, int bssidx)
627 {
628 	wl_p2p_disc_st_t discovery_mode;
629 	s32 ret;
630 	struct net_device *dev;
631 	CFGP2P_DBG(("enter\n"));
632 
633 	if (unlikely(bssidx == WL_INVALID)) {
634 		CFGP2P_ERR((" %d index out of range\n", bssidx));
635 		return -1;
636 	}
637 
638 	dev = wl_cfgp2p_find_ndev(cfg, bssidx);
639 	if (unlikely(dev == NULL)) {
640 		CFGP2P_ERR(("bssidx %d is not assigned\n", bssidx));
641 		return BCME_NOTFOUND;
642 	}
643 
644 #ifdef P2PLISTEN_AP_SAMECHN
645 	CFGP2P_DBG(("p2p0 listen channel %d  AP connection chan %d \n",
646 		channel, cfg->channel));
647 	if ((mode == WL_P2P_DISC_ST_LISTEN) && (cfg->channel == channel)) {
648 		struct net_device *primary_ndev = bcmcfg_to_prmry_ndev(cfg);
649 
650 		if (cfg->p2p_resp_apchn_status) {
651 			CFGP2P_DBG(("p2p_resp_apchn_status already ON \n"));
652 			return BCME_OK;
653 		}
654 
655 		if (wl_get_drv_status(cfg, CONNECTED, primary_ndev)) {
656 			ret = wl_cfg80211_set_p2p_resp_ap_chn(primary_ndev, 1);
657 			cfg->p2p_resp_apchn_status = true;
658 			CFGP2P_DBG(("p2p_resp_apchn_status ON \n"));
659 			return ret;
660 		}
661 	}
662 #endif /* P2PLISTEN_AP_SAMECHN */
663 
664 	/* Put the WL driver into P2P Listen Mode to respond to P2P probe reqs */
665 	discovery_mode.state = mode;
666 	discovery_mode.chspec = wl_ch_host_to_driver(channel);
667 	discovery_mode.dwell = listen_ms;
668 	ret = wldev_iovar_setbuf_bsscfg(dev, "p2p_state", &discovery_mode,
669 		sizeof(discovery_mode), cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
670 		bssidx, &cfg->ioctl_buf_sync);
671 
672 	return ret;
673 }
674 
675 /* Get the index of the P2P Discovery BSS */
676 static s32
wl_cfgp2p_get_disc_idx(struct bcm_cfg80211 * cfg,s32 * index)677 wl_cfgp2p_get_disc_idx(struct bcm_cfg80211 *cfg, s32 *index)
678 {
679 	s32 ret;
680 	struct net_device *dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
681 
682 	ret = wldev_iovar_getint(dev, "p2p_dev", index);
683 	CFGP2P_INFO(("p2p_dev bsscfg_idx=%d ret=%d\n", *index, ret));
684 
685 	if (unlikely(ret <  0)) {
686 	    CFGP2P_ERR(("'p2p_dev' error %d\n", ret));
687 		return ret;
688 	}
689 	return ret;
690 }
691 
wl_cfgp2p_get_conn_idx(struct bcm_cfg80211 * cfg)692 int wl_cfgp2p_get_conn_idx(struct bcm_cfg80211 *cfg)
693 {
694 	int i;
695 	s32 connected_cnt;
696 	dhd_pub_t *dhd =  (dhd_pub_t *)(cfg->pub);
697 	if (!dhd)
698 		return (-ENODEV);
699 	for (i = P2PAPI_BSSCFG_CONNECTION1; i < P2PAPI_BSSCFG_MAX; i++) {
700 		if (wl_to_p2p_bss_bssidx(cfg, i) == -1) {
701 			if (i == P2PAPI_BSSCFG_CONNECTION2) {
702 				if (!(dhd->op_mode & DHD_FLAG_MP2P_MODE)) {
703 					CFGP2P_ERR(("Multi p2p not supported"));
704 					return BCME_ERROR;
705 				}
706 				if ((connected_cnt = wl_get_drv_status_all(cfg, CONNECTED)) > 1) {
707 					CFGP2P_ERR(("Failed to create second p2p interface"
708 						"Already one connection exists"));
709 					return BCME_ERROR;
710 				}
711 			}
712 		return i;
713 		}
714 	}
715 	return BCME_ERROR;
716 }
717 
718 s32
wl_cfgp2p_init_discovery(struct bcm_cfg80211 * cfg)719 wl_cfgp2p_init_discovery(struct bcm_cfg80211 *cfg)
720 {
721 
722 	s32 bssidx = 0;
723 	s32 ret = BCME_OK;
724 	struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
725 
726 	BCM_REFERENCE(ndev);
727 	CFGP2P_DBG(("enter\n"));
728 
729 	if (wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) > 0) {
730 		CFGP2P_ERR(("do nothing, already initialized\n"));
731 		goto exit;
732 	}
733 
734 	ret = wl_cfgp2p_set_discovery(cfg, 1);
735 	if (ret < 0) {
736 		CFGP2P_ERR(("set discover error\n"));
737 		goto exit;
738 	}
739 	/* Enable P2P Discovery in the WL Driver */
740 	ret = wl_cfgp2p_get_disc_idx(cfg, &bssidx);
741 	if (ret < 0) {
742 		goto exit;
743 	}
744 
745 	/* In case of CFG80211 case, check if p2p_discovery interface has allocated p2p_wdev */
746 	if (!cfg->p2p_wdev) {
747 		CFGP2P_ERR(("p2p_wdev is NULL.\n"));
748 		ret = -ENODEV;
749 		goto exit;
750 	}
751 
752 	/* Once p2p also starts using interface_create iovar, the ifidx may change.
753 	 * so that time, the ifidx returned in WLC_E_IF should be used for populating
754 	 * the netinfo
755 	 */
756 	ret = wl_alloc_netinfo(cfg, NULL, cfg->p2p_wdev, WL_IF_TYPE_STA, 0, bssidx, 0);
757 	if (unlikely(ret)) {
758 		goto exit;
759 	}
760 	wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) =
761 	    wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
762 	wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = bssidx;
763 
764 	/* Set the initial discovery state to SCAN */
765 	ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
766 		wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
767 
768 	if (unlikely(ret != 0)) {
769 		CFGP2P_ERR(("unable to set WL_P2P_DISC_ST_SCAN\n"));
770 		wl_cfgp2p_set_discovery(cfg, 0);
771 		wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = 0;
772 		wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) = NULL;
773 		ret = 0;
774 		goto exit;
775 	}
776 
777 	/* Clear our saved WPS and P2P IEs for the discovery BSS */
778 	wl_cfg80211_clear_p2p_disc_ies(cfg);
779 exit:
780 	if (ret) {
781 		wl_flush_fw_log_buffer(ndev, FW_LOGSET_MASK_ALL);
782 	}
783 	return ret;
784 }
785 
786 /* Deinitialize P2P Discovery
787  * Parameters :
788  * @cfg        : wl_private data
789  * Returns 0 if succes
790  */
791 static s32
wl_cfgp2p_deinit_discovery(struct bcm_cfg80211 * cfg)792 wl_cfgp2p_deinit_discovery(struct bcm_cfg80211 *cfg)
793 {
794 	s32 ret = BCME_OK;
795 	s32 bssidx;
796 
797 	CFGP2P_DBG(("enter\n"));
798 	bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
799 	if (bssidx <= 0) {
800 		CFGP2P_ERR(("do nothing, not initialized\n"));
801 		return -1;
802 	}
803 
804 	/* Clear our saved WPS and P2P IEs for the discovery BSS */
805 	wl_cfg80211_clear_p2p_disc_ies(cfg);
806 
807 	/* Set the discovery state to SCAN */
808 	wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
809 	            bssidx);
810 	/* Disable P2P discovery in the WL driver (deletes the discovery BSSCFG) */
811 	ret = wl_cfgp2p_set_discovery(cfg, 0);
812 
813 	/* Remove the p2p disc entry in the netinfo */
814 	wl_dealloc_netinfo_by_wdev(cfg, cfg->p2p_wdev);
815 
816 	wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = WL_INVALID;
817 	wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) = NULL;
818 
819 	return ret;
820 
821 }
822 /* Enable P2P Discovery
823  * Parameters:
824  * @cfg	: wl_private data
825  * @ie  : probe request ie (WPS IE + P2P IE)
826  * @ie_len   : probe request ie length
827  * Returns 0 if success.
828  */
829 s32
wl_cfgp2p_enable_discovery(struct bcm_cfg80211 * cfg,struct net_device * dev,const u8 * ie,u32 ie_len)830 wl_cfgp2p_enable_discovery(struct bcm_cfg80211 *cfg, struct net_device *dev,
831 	const u8 *ie, u32 ie_len)
832 {
833 	s32 ret = BCME_OK;
834 	s32 bssidx;
835 	bcm_struct_cfgdev *cfgdev;
836 
837 	CFGP2P_DBG(("enter\n"));
838 	mutex_lock(&cfg->if_sync);
839 #ifdef WL_IFACE_MGMT
840 	if ((ret = wl_cfg80211_handle_if_role_conflict(cfg, WL_IF_TYPE_P2P_DISC)) != BCME_OK) {
841 		WL_ERR(("secondary iface is active, p2p enable discovery is not supported\n"));
842 		goto exit;
843 	}
844 #endif /* WL_IFACE_MGMT */
845 
846 	if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
847 		CFGP2P_DBG((" DISCOVERY is already initialized, we have nothing to do\n"));
848 		goto set_ie;
849 	}
850 
851 	ret = wl_cfgp2p_init_discovery(cfg);
852 	if (unlikely(ret < 0)) {
853 		CFGP2P_ERR((" init discovery error %d\n", ret));
854 		goto exit;
855 	}
856 
857 	wl_set_p2p_status(cfg, DISCOVERY_ON);
858 	/* Set wsec to any non-zero value in the discovery bsscfg to ensure our
859 	 * P2P probe responses have the privacy bit set in the 802.11 WPA IE.
860 	 * Some peer devices may not initiate WPS with us if this bit is not set.
861 	 */
862 	ret = wldev_iovar_setint_bsscfg(wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE),
863 			"wsec", AES_ENABLED, wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
864 	if (unlikely(ret < 0)) {
865 		CFGP2P_ERR((" wsec error %d\n", ret));
866 	}
867 set_ie:
868 	if (ie_len) {
869 
870 		if (bcmcfg_to_prmry_ndev(cfg) == dev) {
871 			bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
872 		} else if ((bssidx = wl_get_bssidx_by_wdev(cfg, cfg->p2p_wdev)) < 0) {
873 			WL_ERR(("Find p2p index from wdev(%p) failed\n", cfg->p2p_wdev));
874 			ret = BCME_ERROR;
875 			goto exit;
876 		}
877 
878 #if defined(WL_CFG80211_P2P_DEV_IF)
879 		/* For 3.8+ kernels, pass p2p discovery wdev */
880 		cfgdev = cfg->p2p_wdev;
881 #else
882 		/* Prior to 3.8 kernel, there is no netless p2p, so pass p2p0 ndev */
883 		cfgdev = ndev_to_cfgdev(dev);
884 #endif /* WL_CFG80211_P2P_DEV_IF */
885 		ret = wl_cfg80211_set_mgmt_vndr_ies(cfg, cfgdev,
886 				bssidx, VNDR_IE_PRBREQ_FLAG, ie, ie_len);
887 		if (unlikely(ret < 0)) {
888 			CFGP2P_ERR(("set probreq ie occurs error %d\n", ret));
889 			goto exit;
890 		}
891 	}
892 exit:
893 	if (ret) {
894 		wl_flush_fw_log_buffer(dev, FW_LOGSET_MASK_ALL);
895 	}
896 	mutex_unlock(&cfg->if_sync);
897 	return ret;
898 }
899 
900 /* Disable P2P Discovery
901  * Parameters:
902  * @cfg       : wl_private_data
903  * Returns 0 if success.
904  */
905 s32
wl_cfgp2p_disable_discovery(struct bcm_cfg80211 * cfg)906 wl_cfgp2p_disable_discovery(struct bcm_cfg80211 *cfg)
907 {
908 	s32 ret = BCME_OK;
909 	s32 bssidx;
910 
911 	CFGP2P_DBG((" enter\n"));
912 	wl_clr_p2p_status(cfg, DISCOVERY_ON);
913 
914 	if (!cfg->p2p) { // terence 20130113: Fix for p2p NULL pointer
915 		ret = BCME_ERROR;
916 		CFGP2P_ERR(("wl->p2p is NULL\n"));
917 		goto exit;
918 	}
919 
920 #ifdef DHD_IFDEBUG
921 	WL_ERR(("%s: bssidx: %d\n",
922 		__FUNCTION__, (cfg)->p2p->bss[P2PAPI_BSSCFG_DEVICE].bssidx));
923 #endif // endif
924 	bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
925 	if (bssidx <= 0) {
926 		CFGP2P_ERR((" do nothing, not initialized\n"));
927 		return 0;
928 	}
929 
930 	ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0, bssidx);
931 	if (unlikely(ret < 0)) {
932 		CFGP2P_ERR(("unable to set WL_P2P_DISC_ST_SCAN\n"));
933 	}
934 	/* Do a scan abort to stop the driver's scan engine in case it is still
935 	 * waiting out an action frame tx dwell time.
936 	 */
937 #ifdef NOT_YET
938 	if (wl_get_p2p_status(cfg, SCANNING)) {
939 		p2pwlu_scan_abort(hdl, FALSE);
940 	}
941 #endif // endif
942 	wl_clr_p2p_status(cfg, DISCOVERY_ON);
943 	ret = wl_cfgp2p_deinit_discovery(cfg);
944 
945 exit:
946 	return ret;
947 }
948 
949 /* Scan parameters */
950 #define P2PAPI_SCAN_NPROBES 1
951 #define P2PAPI_SCAN_DWELL_TIME_MS 80
952 #define P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS 40
953 #define P2PAPI_SCAN_HOME_TIME_MS 60
954 #define P2PAPI_SCAN_NPROBS_TIME_MS 30
955 #define P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS 100
956 s32
wl_cfgp2p_escan(struct bcm_cfg80211 * cfg,struct net_device * dev,u16 active_scan,u32 num_chans,u16 * channels,s32 search_state,u16 action,u32 bssidx,struct ether_addr * tx_dst_addr,p2p_scan_purpose_t p2p_scan_purpose)957 wl_cfgp2p_escan(struct bcm_cfg80211 *cfg, struct net_device *dev, u16 active_scan,
958 	u32 num_chans, u16 *channels,
959 	s32 search_state, u16 action, u32 bssidx, struct ether_addr *tx_dst_addr,
960 	p2p_scan_purpose_t p2p_scan_purpose)
961 {
962 	s32 ret = BCME_OK;
963 	s32 memsize;
964 	s32 eparams_size;
965 	u32 i;
966 	s8 *memblk;
967 	wl_p2p_scan_t *p2p_params;
968 	wl_escan_params_t *eparams;
969 	wl_escan_params_v2_t *eparams_v2;
970 	wlc_ssid_t ssid;
971 	u32 sync_id = 0;
972 	s32 nprobes = 0;
973 	s32 active_time = 0;
974 	const struct ether_addr *mac_addr = NULL;
975 	u32 scan_type = 0;
976 	struct net_device *pri_dev = NULL;
977 
978 	pri_dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
979 	/* Allocate scan params which need space for 3 channels and 0 ssids */
980 	if (cfg->scan_params_v2) {
981 		eparams_size = (WL_SCAN_PARAMS_V2_FIXED_SIZE +
982 			OFFSETOF(wl_escan_params_v2_t, params)) +
983 			num_chans * sizeof(eparams->params.channel_list[0]);
984 	} else {
985 		eparams_size = (WL_SCAN_PARAMS_FIXED_SIZE +
986 			OFFSETOF(wl_escan_params_t, params)) +
987 			num_chans * sizeof(eparams->params.channel_list[0]);
988 	}
989 
990 	memsize = sizeof(wl_p2p_scan_t) + eparams_size;
991 	memblk = scanparambuf;
992 	if (memsize > sizeof(scanparambuf)) {
993 		CFGP2P_ERR((" scanpar buf too small (%u > %zu)\n",
994 		    memsize, sizeof(scanparambuf)));
995 		return -1;
996 	}
997 	bzero(memblk, memsize);
998 	bzero(cfg->ioctl_buf, WLC_IOCTL_MAXLEN);
999 	if (search_state == WL_P2P_DISC_ST_SEARCH) {
1000 		/*
1001 		 * If we in SEARCH STATE, we don't need to set SSID explictly
1002 		 * because dongle use P2P WILDCARD internally by default
1003 		 */
1004 		wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SEARCH, 0, 0, bssidx);
1005 		/* use null ssid */
1006 		ssid.SSID_len = 0;
1007 		bzero(&ssid.SSID, sizeof(ssid.SSID));
1008 	} else if (search_state == WL_P2P_DISC_ST_SCAN) {
1009 		/* SCAN STATE 802.11 SCAN
1010 		 * WFD Supplicant has p2p_find command with (type=progressive, type= full)
1011 		 * So if P2P_find command with type=progressive,
1012 		 * we have to set ssid to P2P WILDCARD because
1013 		 * we just do broadcast scan unless setting SSID
1014 		 */
1015 		wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0, bssidx);
1016 		/* use wild card ssid */
1017 		ssid.SSID_len = WL_P2P_WILDCARD_SSID_LEN;
1018 		bzero(&ssid.SSID, sizeof(ssid.SSID));
1019 		memcpy(&ssid.SSID, WL_P2P_WILDCARD_SSID, WL_P2P_WILDCARD_SSID_LEN);
1020 	} else {
1021 		CFGP2P_ERR((" invalid search state %d\n", search_state));
1022 		return -1;
1023 	}
1024 
1025 	/* Fill in the P2P scan structure at the start of the iovar param block */
1026 	p2p_params = (wl_p2p_scan_t*) memblk;
1027 	p2p_params->type = 'E';
1028 
1029 	if (!active_scan) {
1030 		scan_type = WL_SCANFLAGS_PASSIVE;
1031 	}
1032 
1033 	if (tx_dst_addr == NULL) {
1034 		mac_addr = &ether_bcast;
1035 	} else {
1036 		mac_addr = tx_dst_addr;
1037 	}
1038 
1039 	switch (p2p_scan_purpose) {
1040 		case P2P_SCAN_SOCIAL_CHANNEL:
1041 			active_time = P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS;
1042 			break;
1043 		case P2P_SCAN_AFX_PEER_NORMAL:
1044 		case P2P_SCAN_AFX_PEER_REDUCED:
1045 			active_time = P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS;
1046 			break;
1047 		case P2P_SCAN_CONNECT_TRY:
1048 			active_time = WL_SCAN_CONNECT_DWELL_TIME_MS;
1049 			break;
1050 		default:
1051 			active_time = wl_get_drv_status_all(cfg, CONNECTED) ?
1052 				-1 : P2PAPI_SCAN_DWELL_TIME_MS;
1053 			break;
1054 	}
1055 
1056 	if (p2p_scan_purpose == P2P_SCAN_CONNECT_TRY) {
1057 		nprobes = active_time /
1058 			WL_SCAN_JOIN_PROBE_INTERVAL_MS;
1059 	} else {
1060 		nprobes = active_time /
1061 			P2PAPI_SCAN_NPROBS_TIME_MS;
1062 	}
1063 
1064 	if (nprobes <= 0) {
1065 		nprobes = 1;
1066 	}
1067 
1068 	wl_escan_set_sync_id(sync_id, cfg);
1069 	/* Fill in the Scan structure that follows the P2P scan structure */
1070 	if (cfg->scan_params_v2) {
1071 		eparams_v2 = (wl_escan_params_v2_t*) (p2p_params + 1);
1072 		eparams_v2->version = htod16(ESCAN_REQ_VERSION_V2);
1073 		eparams_v2->action =  htod16(action);
1074 		eparams_v2->params.version = htod16(WL_SCAN_PARAMS_VERSION_V2);
1075 		eparams_v2->params.length = htod16(sizeof(wl_scan_params_v2_t));
1076 		eparams_v2->params.bss_type = DOT11_BSSTYPE_ANY;
1077 		eparams_v2->params.scan_type = htod32(scan_type);
1078 		(void)memcpy_s(&eparams_v2->params.bssid, ETHER_ADDR_LEN, mac_addr, ETHER_ADDR_LEN);
1079 		eparams_v2->params.home_time = htod32(P2PAPI_SCAN_HOME_TIME_MS);
1080 		eparams_v2->params.active_time = htod32(active_time);
1081 		eparams_v2->params.nprobes = htod32(nprobes);
1082 		eparams_v2->params.passive_time = htod32(-1);
1083 		eparams_v2->sync_id = sync_id;
1084 		for (i = 0; i < num_chans; i++) {
1085 			eparams_v2->params.channel_list[i] =
1086 				wl_ch_host_to_driver(channels[i]);
1087 		}
1088 		eparams_v2->params.channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
1089 			(num_chans & WL_SCAN_PARAMS_COUNT_MASK));
1090 		if (ssid.SSID_len)
1091 			(void)memcpy_s(&eparams_v2->params.ssid,
1092 					sizeof(wlc_ssid_t), &ssid, sizeof(wlc_ssid_t));
1093 		sync_id = eparams_v2->sync_id;
1094 	} else {
1095 		eparams = (wl_escan_params_t*) (p2p_params + 1);
1096 		eparams->version = htod32(ESCAN_REQ_VERSION);
1097 		eparams->action =  htod16(action);
1098 		eparams->params.bss_type = DOT11_BSSTYPE_ANY;
1099 		eparams->params.scan_type = htod32(scan_type);
1100 		(void)memcpy_s(&eparams->params.bssid, ETHER_ADDR_LEN, mac_addr, ETHER_ADDR_LEN);
1101 		eparams->params.home_time = htod32(P2PAPI_SCAN_HOME_TIME_MS);
1102 		eparams->params.active_time = htod32(active_time);
1103 		eparams->params.nprobes = htod32(nprobes);
1104 		eparams->params.passive_time = htod32(-1);
1105 		eparams->sync_id = sync_id;
1106 		for (i = 0; i < num_chans; i++) {
1107 			eparams->params.channel_list[i] =
1108 				wl_ch_host_to_driver(channels[i]);
1109 		}
1110 		eparams->params.channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
1111 			(num_chans & WL_SCAN_PARAMS_COUNT_MASK));
1112 		if (ssid.SSID_len)
1113 			(void)memcpy_s(&eparams->params.ssid,
1114 					sizeof(wlc_ssid_t), &ssid, sizeof(wlc_ssid_t));
1115 		sync_id = eparams->sync_id;
1116 	}
1117 
1118 	wl_escan_set_type(cfg, WL_SCANTYPE_P2P);
1119 
1120 	CFGP2P_DBG(("nprobes:%d active_time:%d\n", nprobes, active_time));
1121 	CFGP2P_DBG(("SCAN CHANNELS : "));
1122 	CFGP2P_DBG(("%d", channels[0]));
1123 	for (i = 1; i < num_chans; i++) {
1124 		CFGP2P_DBG((",%d", channels[i]));
1125 	}
1126 	CFGP2P_DBG(("\n"));
1127 
1128 	ret = wldev_iovar_setbuf_bsscfg(pri_dev, "p2p_scan",
1129 		memblk, memsize, cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
1130 	WL_MSG(dev->name, "P2P_SEARCH sync ID: %d, bssidx: %d\n", sync_id, bssidx);
1131 	if (ret == BCME_OK) {
1132 		wl_set_p2p_status(cfg, SCANNING);
1133 	}
1134 	return ret;
1135 }
1136 
1137 /* search function to reach at common channel to send action frame
1138  * Parameters:
1139  * @cfg       : wl_private data
1140  * @ndev     : net device for bssidx
1141  * @bssidx   : bssidx for BSS
1142  * Returns 0 if success.
1143  */
1144 s32
wl_cfgp2p_act_frm_search(struct bcm_cfg80211 * cfg,struct net_device * ndev,s32 bssidx,s32 channel,struct ether_addr * tx_dst_addr)1145 wl_cfgp2p_act_frm_search(struct bcm_cfg80211 *cfg, struct net_device *ndev,
1146 	s32 bssidx, s32 channel, struct ether_addr *tx_dst_addr)
1147 {
1148 	s32 ret = 0;
1149 	u32 chan_cnt = 0;
1150 	u16 *default_chan_list = NULL;
1151 	p2p_scan_purpose_t p2p_scan_purpose = P2P_SCAN_AFX_PEER_NORMAL;
1152 	if (!p2p_is_on(cfg) || ndev == NULL || bssidx == WL_INVALID)
1153 		return -EINVAL;
1154 	WL_TRACE_HW4((" Enter\n"));
1155 	if (bssidx == wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_PRIMARY))
1156 		bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
1157 	if (channel)
1158 		chan_cnt = AF_PEER_SEARCH_CNT;
1159 	else
1160 		chan_cnt = SOCIAL_CHAN_CNT;
1161 
1162 	if (cfg->afx_hdl->pending_tx_act_frm && cfg->afx_hdl->is_active) {
1163 		wl_action_frame_t *action_frame;
1164 		action_frame = &(cfg->afx_hdl->pending_tx_act_frm->action_frame);
1165 		if (wl_cfgp2p_is_p2p_gas_action(action_frame->data, action_frame->len))	{
1166 			chan_cnt = 1;
1167 			p2p_scan_purpose = P2P_SCAN_AFX_PEER_REDUCED;
1168 		}
1169 	}
1170 
1171 	default_chan_list = (u16 *)MALLOCZ(cfg->osh, chan_cnt * sizeof(*default_chan_list));
1172 	if (default_chan_list == NULL) {
1173 		CFGP2P_ERR(("channel list allocation failed \n"));
1174 		ret = -ENOMEM;
1175 		goto exit;
1176 	}
1177 	if (channel) {
1178 		u32 i;
1179 		/* insert same channel to the chan_list */
1180 		for (i = 0; i < chan_cnt; i++) {
1181 			default_chan_list[i] = channel;
1182 		}
1183 	} else {
1184 		default_chan_list[0] = SOCIAL_CHAN_1;
1185 		default_chan_list[1] = SOCIAL_CHAN_2;
1186 		default_chan_list[2] = SOCIAL_CHAN_3;
1187 	}
1188 	ret = wl_cfgp2p_escan(cfg, ndev, true, chan_cnt,
1189 		default_chan_list, WL_P2P_DISC_ST_SEARCH,
1190 		WL_SCAN_ACTION_START, bssidx, NULL, p2p_scan_purpose);
1191 	MFREE(cfg->osh, default_chan_list, chan_cnt * sizeof(*default_chan_list));
1192 exit:
1193 	return ret;
1194 }
1195 
1196 /* Check whether pointed-to IE looks like WPA. */
1197 #define wl_cfgp2p_is_wpa_ie(ie, tlvs, len)	wl_cfgp2p_has_ie(ie, tlvs, len, \
1198 		(const uint8 *)WPS_OUI, WPS_OUI_LEN, WPA_OUI_TYPE)
1199 /* Check whether pointed-to IE looks like WPS. */
1200 #define wl_cfgp2p_is_wps_ie(ie, tlvs, len)	wl_cfgp2p_has_ie(ie, tlvs, len, \
1201 		(const uint8 *)WPS_OUI, WPS_OUI_LEN, WPS_OUI_TYPE)
1202 /* Check whether the given IE looks like WFA P2P IE. */
1203 #define wl_cfgp2p_is_p2p_ie(ie, tlvs, len)	wl_cfgp2p_has_ie(ie, tlvs, len, \
1204 		(const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_P2P)
1205 /* Check whether the given IE looks like WFA WFDisplay IE. */
1206 #ifndef WFA_OUI_TYPE_WFD
1207 #define WFA_OUI_TYPE_WFD	0x0a			/* WiFi Display OUI TYPE */
1208 #endif // endif
1209 #define wl_cfgp2p_is_wfd_ie(ie, tlvs, len)	wl_cfgp2p_has_ie(ie, tlvs, len, \
1210 		(const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_WFD)
1211 
1212 /* Is any of the tlvs the expected entry? If
1213  * not update the tlvs buffer pointer/length.
1214  */
1215 static bool
wl_cfgp2p_has_ie(const bcm_tlv_t * ie,const u8 ** tlvs,u32 * tlvs_len,const u8 * oui,u32 oui_len,u8 type)1216 wl_cfgp2p_has_ie(const bcm_tlv_t *ie, const u8 **tlvs, u32 *tlvs_len,
1217                  const u8 *oui, u32 oui_len, u8 type)
1218 {
1219 	/* If the contents match the OUI and the type */
1220 	if (ie->len >= oui_len + 1 &&
1221 	    !bcmp(ie->data, oui, oui_len) &&
1222 	    type == ie->data[oui_len]) {
1223 		return TRUE;
1224 	}
1225 
1226 	/* point to the next ie */
1227 	if (tlvs != NULL) {
1228 		bcm_tlv_buffer_advance_past(ie, tlvs, tlvs_len);
1229 	}
1230 
1231 	return FALSE;
1232 }
1233 
1234 const wpa_ie_fixed_t *
wl_cfgp2p_find_wpaie(const u8 * parse,u32 len)1235 wl_cfgp2p_find_wpaie(const u8 *parse, u32 len)
1236 {
1237 	const bcm_tlv_t *ie;
1238 
1239 	while ((ie = bcm_parse_tlvs(parse, len, DOT11_MNG_VS_ID))) {
1240 		if (wl_cfgp2p_is_wpa_ie(ie, &parse, &len)) {
1241 			return (const wpa_ie_fixed_t *)ie;
1242 		}
1243 	}
1244 	return NULL;
1245 }
1246 
1247 const wpa_ie_fixed_t *
wl_cfgp2p_find_wpsie(const u8 * parse,u32 len)1248 wl_cfgp2p_find_wpsie(const u8 *parse, u32 len)
1249 {
1250 	const bcm_tlv_t *ie;
1251 
1252 	while ((ie = bcm_parse_tlvs(parse, len, DOT11_MNG_VS_ID))) {
1253 		if (wl_cfgp2p_is_wps_ie(ie, &parse, &len)) {
1254 			return (const wpa_ie_fixed_t *)ie;
1255 		}
1256 	}
1257 	return NULL;
1258 }
1259 
1260 wifi_p2p_ie_t *
wl_cfgp2p_find_p2pie(const u8 * parse,u32 len)1261 wl_cfgp2p_find_p2pie(const u8 *parse, u32 len)
1262 {
1263 	bcm_tlv_t *ie;
1264 
1265 	while ((ie = bcm_parse_tlvs(parse, len, DOT11_MNG_VS_ID))) {
1266 		if (wl_cfgp2p_is_p2p_ie(ie, &parse, &len)) {
1267 			return (wifi_p2p_ie_t *)ie;
1268 		}
1269 	}
1270 	return NULL;
1271 }
1272 
1273 const wifi_wfd_ie_t *
wl_cfgp2p_find_wfdie(const u8 * parse,u32 len)1274 wl_cfgp2p_find_wfdie(const u8 *parse, u32 len)
1275 {
1276 	const bcm_tlv_t *ie;
1277 
1278 	while ((ie = bcm_parse_tlvs(parse, len, DOT11_MNG_VS_ID))) {
1279 		if (wl_cfgp2p_is_wfd_ie(ie, &parse, &len)) {
1280 			return (const wifi_wfd_ie_t *)ie;
1281 		}
1282 	}
1283 	return NULL;
1284 }
1285 
1286 u32
wl_cfgp2p_vndr_ie(struct bcm_cfg80211 * cfg,u8 * iebuf,s32 pktflag,s8 * oui,s32 ie_id,const s8 * data,s32 datalen,const s8 * add_del_cmd)1287 wl_cfgp2p_vndr_ie(struct bcm_cfg80211 *cfg, u8 *iebuf, s32 pktflag,
1288             s8 *oui, s32 ie_id, const s8 *data, s32 datalen, const s8* add_del_cmd)
1289 {
1290 	vndr_ie_setbuf_t hdr;	/* aligned temporary vndr_ie buffer header */
1291 	s32 iecount;
1292 	u32 data_offset;
1293 
1294 	/* Validate the pktflag parameter */
1295 	if ((pktflag & ~(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG |
1296 	            VNDR_IE_ASSOCRSP_FLAG | VNDR_IE_AUTHRSP_FLAG |
1297 	            VNDR_IE_PRBREQ_FLAG | VNDR_IE_ASSOCREQ_FLAG |
1298 	            VNDR_IE_DISASSOC_FLAG))) {
1299 		CFGP2P_ERR(("p2pwl_vndr_ie: Invalid packet flag 0x%x\n", pktflag));
1300 		return -1;
1301 	}
1302 
1303 	/* Copy the vndr_ie SET command ("add"/"del") to the buffer */
1304 	strlcpy(hdr.cmd, add_del_cmd, sizeof(hdr.cmd));
1305 
1306 	/* Set the IE count - the buffer contains only 1 IE */
1307 	iecount = htod32(1);
1308 	memcpy((void *)&hdr.vndr_ie_buffer.iecount, &iecount, sizeof(s32));
1309 
1310 	/* For vendor ID DOT11_MNG_ID_EXT_ID, need to set pkt flag to VNDR_IE_CUSTOM_FLAG */
1311 	if (ie_id == DOT11_MNG_ID_EXT_ID) {
1312 		pktflag = pktflag | VNDR_IE_CUSTOM_FLAG;
1313 	}
1314 
1315 	/* Copy packet flags that indicate which packets will contain this IE */
1316 	pktflag = htod32(pktflag);
1317 	memcpy((void *)&hdr.vndr_ie_buffer.vndr_ie_list[0].pktflag, &pktflag,
1318 		sizeof(u32));
1319 
1320 	/* Add the IE ID to the buffer */
1321 	hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.id = ie_id;
1322 
1323 	/* Add the IE length to the buffer */
1324 	hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.len =
1325 		(uint8) VNDR_IE_MIN_LEN + datalen;
1326 
1327 	/* Add the IE OUI to the buffer */
1328 	hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui[0] = oui[0];
1329 	hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui[1] = oui[1];
1330 	hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui[2] = oui[2];
1331 
1332 	/* Copy the aligned temporary vndr_ie buffer header to the IE buffer */
1333 	memcpy(iebuf, &hdr, sizeof(hdr) - 1);
1334 
1335 	/* Copy the IE data to the IE buffer */
1336 	data_offset =
1337 		(u8*)&hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.data[0] -
1338 		(u8*)&hdr;
1339 	memcpy(iebuf + data_offset, data, datalen);
1340 	return data_offset + datalen;
1341 
1342 }
1343 
1344 struct net_device *
wl_cfgp2p_find_ndev(struct bcm_cfg80211 * cfg,s32 bssidx)1345 wl_cfgp2p_find_ndev(struct bcm_cfg80211 *cfg, s32 bssidx)
1346 {
1347 	u32 i;
1348 	struct net_device *ndev = NULL;
1349 	if (bssidx < 0) {
1350 		CFGP2P_ERR((" bsscfg idx is invalid\n"));
1351 		goto exit;
1352 	}
1353 
1354 	for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) {
1355 		if (bssidx == wl_to_p2p_bss_bssidx(cfg, i)) {
1356 			ndev = wl_to_p2p_bss_ndev(cfg, i);
1357 			break;
1358 		}
1359 	}
1360 
1361 exit:
1362 	return ndev;
1363 }
1364 /*
1365  * Search the driver array idx based on bssidx argument
1366  * Parameters: Note that this idx is applicable only
1367  * for primary and P2P interfaces. The virtual AP/STA is not
1368  * covered here.
1369  * @cfg     : wl_private data
1370  * @bssidx : bssidx which indicate bsscfg->idx of firmware.
1371  * @type   : output arg to store array idx of p2p->bss.
1372  * Returns error
1373  */
1374 
1375 s32
wl_cfgp2p_find_type(struct bcm_cfg80211 * cfg,s32 bssidx,s32 * type)1376 wl_cfgp2p_find_type(struct bcm_cfg80211 *cfg, s32 bssidx, s32 *type)
1377 {
1378 	u32 i;
1379 	if (bssidx < 0 || type == NULL) {
1380 		CFGP2P_ERR((" argument is invalid\n"));
1381 		goto exit;
1382 	}
1383 	if (!cfg->p2p) {
1384 		CFGP2P_ERR(("p2p if does not exist\n"));
1385 		goto exit;
1386 	}
1387 	for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) {
1388 		if (bssidx == wl_to_p2p_bss_bssidx(cfg, i)) {
1389 			*type = i;
1390 			return BCME_OK;
1391 		}
1392 	}
1393 
1394 exit:
1395 	return BCME_BADARG;
1396 }
1397 
1398 /*
1399  * Callback function for WLC_E_P2P_DISC_LISTEN_COMPLETE
1400  */
1401 s32
wl_cfgp2p_listen_complete(struct bcm_cfg80211 * cfg,bcm_struct_cfgdev * cfgdev,const wl_event_msg_t * e,void * data)1402 wl_cfgp2p_listen_complete(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
1403 	const wl_event_msg_t *e, void *data)
1404 {
1405 	s32 ret = BCME_OK;
1406 	struct net_device *ndev = NULL;
1407 
1408 	if (!cfg || !cfg->p2p || !cfgdev)
1409 		return BCME_ERROR;
1410 
1411 	CFGP2P_DBG((" Enter\n"));
1412 #ifdef DHD_IFDEBUG
1413 	PRINT_WDEV_INFO(cfgdev);
1414 #endif /* DHD_IFDEBUG */
1415 
1416 	ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
1417 
1418 #ifdef P2P_LISTEN_OFFLOADING
1419 	if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
1420 		wl_clr_p2p_status(cfg, DISC_IN_PROGRESS);
1421 		CFGP2P_ERR(("DISC_IN_PROGRESS cleared\n"));
1422 		if (ndev && (ndev->ieee80211_ptr != NULL)) {
1423 #if defined(WL_CFG80211_P2P_DEV_IF)
1424 			if (cfgdev && ((struct wireless_dev *)cfgdev)->wiphy) {
1425 				cfg80211_remain_on_channel_expired(cfgdev, cfg->last_roc_id,
1426 						&cfg->remain_on_chan, GFP_KERNEL);
1427 			} else {
1428 				CFGP2P_ERR(("Invalid cfgdev. Dropping the"
1429 						"remain_on_channel_expired event.\n"));
1430 			}
1431 #else
1432 			cfg80211_remain_on_channel_expired(cfgdev, cfg->last_roc_id,
1433 					&cfg->remain_on_chan, cfg->remain_on_chan_type, GFP_KERNEL);
1434 #endif /* WL_CFG80211_P2P_DEV_IF */
1435 
1436 #ifdef CONFIG_AP6XXX_WIFI6_HDF
1437 			ret = HdfWifiEventCancelRemainOnChannel(get_hdf_netdev(g_event_ifidx), cfg->remain_on_chan.center_freq);
1438 			WL_ERR(("HdfWifiEventCancelRemainOnChannel ret=%d\n", ret));
1439 #endif
1440 		}
1441 	}
1442 #endif /* P2P_LISTEN_OFFLOADING */
1443 
1444 	if (wl_get_p2p_status(cfg, LISTEN_EXPIRED) == 0) {
1445 		wl_set_p2p_status(cfg, LISTEN_EXPIRED);
1446 		if (timer_pending(&cfg->p2p->listen_timer)) {
1447 			del_timer_sync(&cfg->p2p->listen_timer);
1448 		}
1449 
1450 		if (cfg->afx_hdl->is_listen == TRUE &&
1451 			wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
1452 			WL_DBG(("Listen DONE for action frame\n"));
1453 			complete(&cfg->act_frm_scan);
1454 		}
1455 #ifdef WL_CFG80211_SYNC_GON
1456 		else if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN)) {
1457 			wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM_LISTEN, ndev);
1458 			WL_DBG(("Listen DONE and wake up wait_next_af !!(%d)\n",
1459 				jiffies_to_msecs(jiffies - cfg->af_tx_sent_jiffies)));
1460 
1461 			if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM))
1462 				wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
1463 
1464 			complete(&cfg->wait_next_af);
1465 		}
1466 #endif /* WL_CFG80211_SYNC_GON */
1467 
1468 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
1469 		if (wl_get_drv_status_all(cfg, REMAINING_ON_CHANNEL))
1470 #else
1471 		if (wl_get_drv_status_all(cfg, REMAINING_ON_CHANNEL) ||
1472 			wl_get_drv_status_all(cfg, FAKE_REMAINING_ON_CHANNEL))
1473 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
1474 		{
1475 			WL_DBG(("Listen DONE for remain on channel expired\n"));
1476 			wl_clr_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
1477 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
1478 			wl_clr_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
1479 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
1480 			if (ndev && (ndev->ieee80211_ptr != NULL)) {
1481 #if defined(WL_CFG80211_P2P_DEV_IF)
1482 				if (cfgdev && ((struct wireless_dev *)cfgdev)->wiphy &&
1483 				    bcmcfg_to_p2p_wdev(cfg)) {
1484 					/*
1485 					 * To prevent kernel panic,
1486 					 * if cfgdev->wiphy may be invalid, adding explicit check
1487 					 */
1488 					cfg80211_remain_on_channel_expired(bcmcfg_to_p2p_wdev(cfg),
1489 						cfg->last_roc_id, &cfg->remain_on_chan, GFP_KERNEL);
1490 #ifdef CONFIG_AP6XXX_WIFI6_HDF
1491 					ret = HdfWifiEventCancelRemainOnChannel(get_hdf_netdev(g_event_ifidx), cfg->remain_on_chan.center_freq);
1492 					WL_ERR(("HdfWifiEventCancelRemainOnChannel ret=%d\n", ret));
1493 #endif
1494 				} else
1495 					CFGP2P_ERR(("Invalid cfgdev. Dropping the"
1496 						"remain_on_channel_expired event.\n"));
1497 #else
1498 				if (cfgdev && ((struct wireless_dev *)cfgdev)->wiphy)
1499 					cfg80211_remain_on_channel_expired(cfgdev,
1500 						cfg->last_roc_id, &cfg->remain_on_chan,
1501 						cfg->remain_on_chan_type, GFP_KERNEL);
1502 
1503 #ifdef CONFIG_AP6XXX_WIFI6_HDF
1504 				ret = HdfWifiEventCancelRemainOnChannel(get_hdf_netdev(g_event_ifidx), cfg->remain_on_chan.center_freq);
1505 				WL_ERR(("HdfWifiEventCancelRemainOnChannel ret=%d\n", ret));
1506 #endif
1507 #endif /* WL_CFG80211_P2P_DEV_IF */
1508 			}
1509 		}
1510 		if (wl_add_remove_eventmsg(bcmcfg_to_prmry_ndev(cfg),
1511 			WLC_E_P2P_PROBREQ_MSG, false) != BCME_OK) {
1512 			CFGP2P_ERR((" failed to unset WLC_E_P2P_PROPREQ_MSG\n"));
1513 		}
1514 	} else
1515 		wl_clr_p2p_status(cfg, LISTEN_EXPIRED);
1516 
1517 	return ret;
1518 
1519 }
1520 
1521 /*
1522  *  Timer expire callback function for LISTEN
1523  *  We can't report cfg80211_remain_on_channel_expired from Timer ISR context,
1524  *  so lets do it from thread context.
1525  */
1526 void
wl_cfgp2p_listen_expired(unsigned long data)1527 wl_cfgp2p_listen_expired(unsigned long data)
1528 {
1529 	wl_event_msg_t msg;
1530 	struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *) data;
1531 	struct net_device *ndev;
1532 	CFGP2P_DBG((" Enter\n"));
1533 
1534 	if (!cfg) {
1535 		CFGP2P_ERR((" No cfg\n"));
1536 		return;
1537 	}
1538 	bzero(&msg, sizeof(wl_event_msg_t));
1539 	msg.event_type =  hton32(WLC_E_P2P_DISC_LISTEN_COMPLETE);
1540 	msg.bsscfgidx  =  wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
1541 #if defined(WL_ENABLE_P2P_IF)
1542 	ndev = cfg->p2p_net ? cfg->p2p_net :
1543 		wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE);
1544 #else
1545 	ndev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE);
1546 #endif /* WL_ENABLE_P2P_IF */
1547 	if (!ndev) {
1548 		CFGP2P_ERR((" No ndev\n"));
1549 		return;
1550 	}
1551 	wl_cfg80211_event(ndev, &msg, NULL);
1552 }
1553 /*
1554  *  Routine for cancelling the P2P LISTEN
1555  */
1556 static s32
wl_cfgp2p_cancel_listen(struct bcm_cfg80211 * cfg,struct net_device * ndev,struct wireless_dev * wdev,bool notify)1557 wl_cfgp2p_cancel_listen(struct bcm_cfg80211 *cfg, struct net_device *ndev,
1558                          struct wireless_dev *wdev, bool notify)
1559 {
1560 	WL_DBG(("Enter \n"));
1561 	/* Irrespective of whether timer is running or not, reset
1562 	 * the LISTEN state.
1563 	 */
1564 #ifdef NOT_YET
1565 	wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
1566 		wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
1567 #endif /* NOT_YET */
1568 	if (timer_pending(&cfg->p2p->listen_timer)) {
1569 		del_timer_sync(&cfg->p2p->listen_timer);
1570 		if (notify) {
1571 #if defined(WL_CFG80211_P2P_DEV_IF)
1572 			if (bcmcfg_to_p2p_wdev(cfg))
1573 				cfg80211_remain_on_channel_expired(wdev, cfg->last_roc_id,
1574 					&cfg->remain_on_chan, GFP_KERNEL);
1575 #else
1576 			if (ndev && ndev->ieee80211_ptr)
1577 				cfg80211_remain_on_channel_expired(ndev, cfg->last_roc_id,
1578 					&cfg->remain_on_chan, cfg->remain_on_chan_type, GFP_KERNEL);
1579 #endif /* WL_CFG80211_P2P_DEV_IF */
1580 
1581 #ifdef CONFIG_AP6XXX_WIFI6_HDF
1582 			int ret =0;
1583 			ret = HdfWifiEventCancelRemainOnChannel(get_hdf_netdev(g_event_ifidx), cfg->remain_on_chan.center_freq);
1584 			WL_ERR(("HdfWifiEventCancelRemainOnChannel ret=%d\n", ret));
1585 #endif
1586 		}
1587 	}
1588 	return 0;
1589 }
1590 /*
1591  * Do a P2P Listen on the given channel for the given duration.
1592  * A listen consists of sitting idle and responding to P2P probe requests
1593  * with a P2P probe response.
1594  *
1595  * This fn assumes dongle p2p device discovery is already enabled.
1596  * Parameters   :
1597  * @cfg          : wl_private data
1598  * @channel     : channel to listen
1599  * @duration_ms : the time (milli seconds) to wait
1600  */
1601 s32
wl_cfgp2p_discover_listen(struct bcm_cfg80211 * cfg,s32 channel,u32 duration_ms)1602 wl_cfgp2p_discover_listen(struct bcm_cfg80211 *cfg, s32 channel, u32 duration_ms)
1603 {
1604 #define EXTRA_DELAY_TIME	100
1605 	s32 ret = BCME_OK;
1606 	timer_list_compat_t *_timer;
1607 	s32 extra_delay;
1608 	struct net_device *netdev = bcmcfg_to_prmry_ndev(cfg);
1609 
1610 	CFGP2P_DBG((" Enter Listen Channel : %d, Duration : %d\n", channel, duration_ms));
1611 	if (unlikely(wl_get_p2p_status(cfg, DISCOVERY_ON) == 0)) {
1612 
1613 		CFGP2P_ERR((" Discovery is not set, so we have noting to do\n"));
1614 
1615 		ret = BCME_NOTREADY;
1616 		goto exit;
1617 	}
1618 	if (timer_pending(&cfg->p2p->listen_timer)) {
1619 		CFGP2P_DBG(("previous LISTEN is not completed yet\n"));
1620 		goto exit;
1621 
1622 	}
1623 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
1624 	else
1625 		wl_clr_p2p_status(cfg, LISTEN_EXPIRED);
1626 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
1627 	if (wl_add_remove_eventmsg(netdev, WLC_E_P2P_PROBREQ_MSG, true) != BCME_OK) {
1628 			CFGP2P_ERR((" failed to set WLC_E_P2P_PROPREQ_MSG\n"));
1629 	}
1630 
1631 	ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_LISTEN, channel, (u16) duration_ms,
1632 	            wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
1633 	_timer = &cfg->p2p->listen_timer;
1634 
1635 	/*  We will wait to receive WLC_E_P2P_DISC_LISTEN_COMPLETE from dongle ,
1636 	 *  otherwise we will wait up to duration_ms + 100ms + duration / 10
1637 	 */
1638 	if (ret == BCME_OK) {
1639 		extra_delay = EXTRA_DELAY_TIME + (duration_ms / 10);
1640 	} else {
1641 		/* if failed to set listen, it doesn't need to wait whole duration. */
1642 		duration_ms = 100 + duration_ms / 20;
1643 		extra_delay = 0;
1644 	}
1645 
1646 	INIT_TIMER(_timer, wl_cfgp2p_listen_expired, duration_ms, extra_delay);
1647 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
1648 	wl_clr_p2p_status(cfg, LISTEN_EXPIRED);
1649 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
1650 
1651 #undef EXTRA_DELAY_TIME
1652 exit:
1653 	return ret;
1654 }
1655 
1656 s32
wl_cfgp2p_discover_enable_search(struct bcm_cfg80211 * cfg,u8 enable)1657 wl_cfgp2p_discover_enable_search(struct bcm_cfg80211 *cfg, u8 enable)
1658 {
1659 	s32 ret = BCME_OK;
1660 	CFGP2P_DBG((" Enter\n"));
1661 	if (!wl_get_p2p_status(cfg, DISCOVERY_ON)) {
1662 
1663 		CFGP2P_DBG((" do nothing, discovery is off\n"));
1664 		return ret;
1665 	}
1666 	if (wl_get_p2p_status(cfg, SEARCH_ENABLED) == enable) {
1667 		CFGP2P_DBG(("already : %d\n", enable));
1668 		return ret;
1669 	}
1670 
1671 	wl_chg_p2p_status(cfg, SEARCH_ENABLED);
1672 	/* When disabling Search, reset the WL driver's p2p discovery state to
1673 	 * WL_P2P_DISC_ST_SCAN.
1674 	 */
1675 	if (!enable) {
1676 		wl_clr_p2p_status(cfg, SCANNING);
1677 		ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
1678 		            wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
1679 	}
1680 
1681 	return ret;
1682 }
1683 
1684 /*
1685  * Callback function for WLC_E_ACTION_FRAME_COMPLETE, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE
1686  */
1687 s32
wl_cfgp2p_action_tx_complete(struct bcm_cfg80211 * cfg,bcm_struct_cfgdev * cfgdev,const wl_event_msg_t * e,void * data)1688 wl_cfgp2p_action_tx_complete(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
1689             const wl_event_msg_t *e, void *data)
1690 {
1691 	s32 ret = BCME_OK;
1692 	u32 event_type = ntoh32(e->event_type);
1693 	u32 status = ntoh32(e->status);
1694 	struct net_device *ndev = NULL;
1695 	u8 bsscfgidx = e->bsscfgidx;
1696 
1697 	CFGP2P_DBG((" Enter\n"));
1698 
1699 	ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
1700 
1701 	if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM)) {
1702 		if (event_type == WLC_E_ACTION_FRAME_COMPLETE) {
1703 
1704 			CFGP2P_DBG((" WLC_E_ACTION_FRAME_COMPLETE is received : %d\n", status));
1705 			if (status == WLC_E_STATUS_SUCCESS) {
1706 				wl_set_p2p_status(cfg, ACTION_TX_COMPLETED);
1707 				CFGP2P_ACTION(("TX actfrm : ACK\n"));
1708 				if (!cfg->need_wait_afrx && cfg->af_sent_channel) {
1709 					CFGP2P_DBG(("no need to wait next AF.\n"));
1710 					wl_stop_wait_next_action_frame(cfg, ndev, bsscfgidx);
1711 				}
1712 			}
1713 			else if (!wl_get_p2p_status(cfg, ACTION_TX_COMPLETED)) {
1714 				wl_set_p2p_status(cfg, ACTION_TX_NOACK);
1715 				if (status == WLC_E_STATUS_SUPPRESS) {
1716 					CFGP2P_ACTION(("TX actfrm : SUPPRES\n"));
1717 				} else {
1718 					CFGP2P_ACTION(("TX actfrm : NO ACK\n"));
1719 				}
1720 				wl_stop_wait_next_action_frame(cfg, ndev, bsscfgidx);
1721 			}
1722 		} else {
1723 			CFGP2P_DBG((" WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE is received,"
1724 						"status : %d\n", status));
1725 
1726 			if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM))
1727 				complete(&cfg->send_af_done);
1728 		}
1729 	}
1730 	return ret;
1731 }
1732 /* Send an action frame immediately without doing channel synchronization.
1733  *
1734  * This function does not wait for a completion event before returning.
1735  * The WLC_E_ACTION_FRAME_COMPLETE event will be received when the action
1736  * frame is transmitted.
1737  * The WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE event will be received when an
1738  * 802.11 ack has been received for the sent action frame.
1739  */
1740 s32
wl_cfgp2p_tx_action_frame(struct bcm_cfg80211 * cfg,struct net_device * dev,wl_af_params_t * af_params,s32 bssidx)1741 wl_cfgp2p_tx_action_frame(struct bcm_cfg80211 *cfg, struct net_device *dev,
1742 	wl_af_params_t *af_params, s32 bssidx)
1743 {
1744 	s32 ret = BCME_OK;
1745 	s32 evt_ret = BCME_OK;
1746 	s32 timeout = 0;
1747 	wl_eventmsg_buf_t buf;
1748 
1749 	CFGP2P_DBG(("\n"));
1750 	CFGP2P_DBG(("channel : %u , dwell time : %u\n",
1751 	    af_params->channel, af_params->dwell_time));
1752 
1753 	wl_clr_p2p_status(cfg, ACTION_TX_COMPLETED);
1754 	wl_clr_p2p_status(cfg, ACTION_TX_NOACK);
1755 
1756 	bzero(&buf, sizeof(wl_eventmsg_buf_t));
1757 	wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE, true);
1758 	wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_COMPLETE, true);
1759 	if ((evt_ret = wl_cfg80211_apply_eventbuffer(bcmcfg_to_prmry_ndev(cfg), cfg, &buf)) < 0)
1760 		return evt_ret;
1761 
1762 	cfg->af_sent_channel  = af_params->channel;
1763 #ifdef WL_CFG80211_SYNC_GON
1764 	cfg->af_tx_sent_jiffies = jiffies;
1765 #endif /* WL_CFG80211_SYNC_GON */
1766 
1767 	ret = wldev_iovar_setbuf_bsscfg(dev, "actframe", af_params, sizeof(*af_params),
1768 		cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
1769 
1770 	if (ret < 0) {
1771 		CFGP2P_ACTION(("TX actfrm : ERROR\n"));
1772 		goto exit;
1773 	}
1774 
1775 	timeout = wait_for_completion_timeout(&cfg->send_af_done,
1776 		msecs_to_jiffies(af_params->dwell_time + WL_AF_TX_EXTRA_TIME_MAX));
1777 
1778 	if (timeout >= 0 && wl_get_p2p_status(cfg, ACTION_TX_COMPLETED)) {
1779 		CFGP2P_DBG(("tx action frame operation is completed\n"));
1780 		ret = BCME_OK;
1781 	} else if (ETHER_ISBCAST(&cfg->afx_hdl->tx_dst_addr)) {
1782 		CFGP2P_DBG(("bcast tx action frame operation is completed\n"));
1783 		ret = BCME_OK;
1784 	} else {
1785 		ret = BCME_ERROR;
1786 		CFGP2P_DBG(("tx action frame operation is failed\n"));
1787 	}
1788 	/* clear status bit for action tx */
1789 	wl_clr_p2p_status(cfg, ACTION_TX_COMPLETED);
1790 	wl_clr_p2p_status(cfg, ACTION_TX_NOACK);
1791 
1792 exit:
1793 	CFGP2P_DBG((" via act frame iovar : status = %d\n", ret));
1794 
1795 	bzero(&buf, sizeof(wl_eventmsg_buf_t));
1796 	wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE, false);
1797 	wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_COMPLETE, false);
1798 	if ((evt_ret = wl_cfg80211_apply_eventbuffer(bcmcfg_to_prmry_ndev(cfg), cfg, &buf)) < 0) {
1799 		WL_ERR(("TX frame events revert back failed \n"));
1800 		return evt_ret;
1801 	}
1802 
1803 	return ret;
1804 }
1805 
1806 /* Generate our P2P Device Address and P2P Interface Address from our primary
1807  * MAC address.
1808  */
1809 void
wl_cfgp2p_generate_bss_mac(struct bcm_cfg80211 * cfg,struct ether_addr * primary_addr)1810 wl_cfgp2p_generate_bss_mac(struct bcm_cfg80211 *cfg, struct ether_addr *primary_addr)
1811 {
1812 	struct ether_addr *mac_addr = wl_to_p2p_bss_macaddr(cfg, P2PAPI_BSSCFG_DEVICE);
1813 	struct ether_addr *int_addr;
1814 
1815 #ifdef WL_P2P_USE_RANDMAC
1816 	dhd_generate_mac_addr(mac_addr);
1817 #else
1818 	memcpy(mac_addr, primary_addr, sizeof(struct ether_addr));
1819 	mac_addr->octet[0] |= 0x02;
1820 	WL_DBG(("P2P Discovery address:"MACDBG "\n", MAC2STRDBG(mac_addr->octet)));
1821 #endif /* WL_P2P_USE_RANDMAC */
1822 
1823 	int_addr = wl_to_p2p_bss_macaddr(cfg, P2PAPI_BSSCFG_CONNECTION1);
1824 	memcpy(int_addr, mac_addr, sizeof(struct ether_addr));
1825 	int_addr->octet[4] ^= 0x80;
1826 	WL_DBG(("Primary P2P Interface address:"MACDBG "\n", MAC2STRDBG(int_addr->octet)));
1827 
1828 	int_addr = wl_to_p2p_bss_macaddr(cfg, P2PAPI_BSSCFG_CONNECTION2);
1829 	memcpy(int_addr, mac_addr, sizeof(struct ether_addr));
1830 	int_addr->octet[4] ^= 0x90;
1831 }
1832 
1833 /* P2P IF Address change to Virtual Interface MAC Address */
1834 void
wl_cfg80211_change_ifaddr(u8 * buf,struct ether_addr * p2p_int_addr,u8 element_id)1835 wl_cfg80211_change_ifaddr(u8* buf, struct ether_addr *p2p_int_addr, u8 element_id)
1836 {
1837 	wifi_p2p_ie_t *ie = (wifi_p2p_ie_t*) buf;
1838 	u16 len = ie->len;
1839 	u8 *subel;
1840 	u8 subelt_id;
1841 	u16 subelt_len;
1842 	CFGP2P_DBG((" Enter\n"));
1843 
1844 	/* Point subel to the P2P IE's subelt field.
1845 	 * Subtract the preceding fields (id, len, OUI, oui_type) from the length.
1846 	 */
1847 	subel = ie->subelts;
1848 	len -= 4;	/* exclude OUI + OUI_TYPE */
1849 
1850 	while (len >= 3) {
1851 	/* attribute id */
1852 		subelt_id = *subel;
1853 		subel += 1;
1854 		len -= 1;
1855 
1856 		/* 2-byte little endian */
1857 		subelt_len = *subel++;
1858 		subelt_len |= *subel++ << 8;
1859 
1860 		len -= 2;
1861 		len -= subelt_len;	/* for the remaining subelt fields */
1862 
1863 		if (subelt_id == element_id) {
1864 			if (subelt_id == P2P_SEID_INTINTADDR) {
1865 				memcpy(subel, p2p_int_addr->octet, ETHER_ADDR_LEN);
1866 				CFGP2P_INFO(("Intended P2P Interface Address ATTR FOUND\n"));
1867 			} else if (subelt_id == P2P_SEID_DEV_ID) {
1868 				memcpy(subel, p2p_int_addr->octet, ETHER_ADDR_LEN);
1869 				CFGP2P_INFO(("Device ID ATTR FOUND\n"));
1870 			} else if (subelt_id == P2P_SEID_DEV_INFO) {
1871 				memcpy(subel, p2p_int_addr->octet, ETHER_ADDR_LEN);
1872 				CFGP2P_INFO(("Device INFO ATTR FOUND\n"));
1873 			} else if (subelt_id == P2P_SEID_GROUP_ID) {
1874 				memcpy(subel, p2p_int_addr->octet, ETHER_ADDR_LEN);
1875 				CFGP2P_INFO(("GROUP ID ATTR FOUND\n"));
1876 			}			return;
1877 		} else {
1878 			CFGP2P_DBG(("OTHER id : %d\n", subelt_id));
1879 		}
1880 		subel += subelt_len;
1881 	}
1882 }
1883 
1884 s32
wl_cfgp2p_supported(struct bcm_cfg80211 * cfg,struct net_device * ndev)1885 wl_cfgp2p_supported(struct bcm_cfg80211 *cfg, struct net_device *ndev)
1886 {
1887 	s32 ret = BCME_OK;
1888 	s32 p2p_supported = 0;
1889 	ret = wldev_iovar_getint(ndev, "p2p",
1890 	               &p2p_supported);
1891 	if (ret < 0) {
1892 		if (ret == BCME_UNSUPPORTED) {
1893 			CFGP2P_INFO(("p2p is unsupported\n"));
1894 			return 0;
1895 		} else {
1896 			CFGP2P_ERR(("cfg p2p error %d\n", ret));
1897 			return ret;
1898 		}
1899 	}
1900 	if (cfg->pub->conf->fw_type == FW_TYPE_MESH)
1901 		p2p_supported = 0;
1902 	if (p2p_supported == 1) {
1903 		CFGP2P_INFO(("p2p is supported\n"));
1904 	} else {
1905 		CFGP2P_INFO(("p2p is unsupported\n"));
1906 		p2p_supported = 0;
1907 	}
1908 	return p2p_supported;
1909 }
1910 
1911 /* Cleanup P2P resources */
1912 s32
wl_cfgp2p_down(struct bcm_cfg80211 * cfg)1913 wl_cfgp2p_down(struct bcm_cfg80211 *cfg)
1914 {
1915 	struct net_device *ndev = NULL;
1916 	struct wireless_dev *wdev = NULL;
1917 
1918 #if defined(WL_CFG80211_P2P_DEV_IF)
1919 	ndev = bcmcfg_to_prmry_ndev(cfg);
1920 	wdev = bcmcfg_to_p2p_wdev(cfg);
1921 #elif defined(WL_ENABLE_P2P_IF)
1922 	ndev = cfg->p2p_net ? cfg->p2p_net : bcmcfg_to_prmry_ndev(cfg);
1923 	wdev = ndev_to_wdev(ndev);
1924 #endif /* WL_CFG80211_P2P_DEV_IF */
1925 
1926 	wl_cfgp2p_cancel_listen(cfg, ndev, wdev, TRUE);
1927 	wl_cfgp2p_disable_discovery(cfg);
1928 
1929 #if defined(WL_CFG80211_P2P_DEV_IF) && !defined(KEEP_WIFION_OPTION)
1930 /*
1931  * In CUSTOMER_HW4 implementation "ifconfig wlan0 down" can get
1932  * called during phone suspend and customer requires the p2p
1933  * discovery interface to be left untouched so that the user
1934  * space can resume without any problem.
1935  */
1936 	if (cfg->p2p_wdev) {
1937 		/* If p2p wdev is left out, clean it up */
1938 		WL_ERR(("Clean up the p2p discovery IF\n"));
1939 		wl_cfgp2p_del_p2p_disc_if(cfg->p2p_wdev, cfg);
1940 	}
1941 #endif /* WL_CFG80211_P2P_DEV_IF !defined(KEEP_WIFION_OPTION) */
1942 
1943 	wl_cfgp2p_deinit_priv(cfg);
1944 	return 0;
1945 }
1946 
wl_cfgp2p_vif_created(struct bcm_cfg80211 * cfg)1947 int wl_cfgp2p_vif_created(struct bcm_cfg80211 *cfg)
1948 {
1949 	if (cfg->p2p && ((wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION1) != -1) ||
1950 		(wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION2) != -1)))
1951 		return true;
1952 	else
1953 		return false;
1954 
1955 }
1956 
1957 s32
wl_cfgp2p_set_p2p_noa(struct bcm_cfg80211 * cfg,struct net_device * ndev,char * buf,int len)1958 wl_cfgp2p_set_p2p_noa(struct bcm_cfg80211 *cfg, struct net_device *ndev, char* buf, int len)
1959 {
1960 	s32 ret = -1;
1961 	int count, start, duration;
1962 	wl_p2p_sched_t dongle_noa;
1963 	s32 bssidx, type;
1964 	int iovar_len = sizeof(dongle_noa);
1965 	CFGP2P_DBG((" Enter\n"));
1966 
1967 	bzero(&dongle_noa, sizeof(dongle_noa));
1968 
1969 	if (wl_cfgp2p_vif_created(cfg)) {
1970 		cfg->p2p->noa.desc[0].start = 0;
1971 
1972 		sscanf(buf, "%10d %10d %10d", &count, &start, &duration);
1973 		CFGP2P_DBG(("set_p2p_noa count %d start %d duration %d\n",
1974 			count, start, duration));
1975 		if (count != -1)
1976 			cfg->p2p->noa.desc[0].count = count;
1977 
1978 		/* supplicant gives interval as start */
1979 		if (start != -1)
1980 			cfg->p2p->noa.desc[0].interval = start;
1981 
1982 		if (duration != -1)
1983 			cfg->p2p->noa.desc[0].duration = duration;
1984 
1985 		if (cfg->p2p->noa.desc[0].count != 255 && cfg->p2p->noa.desc[0].count != 0) {
1986 			cfg->p2p->noa.desc[0].start = 200;
1987 			dongle_noa.type = WL_P2P_SCHED_TYPE_REQ_ABS;
1988 			dongle_noa.action = WL_P2P_SCHED_ACTION_GOOFF;
1989 			dongle_noa.option = WL_P2P_SCHED_OPTION_TSFOFS;
1990 		}
1991 		else if (cfg->p2p->noa.desc[0].count == 0) {
1992 			cfg->p2p->noa.desc[0].start = 0;
1993 			dongle_noa.type = WL_P2P_SCHED_TYPE_ABS;
1994 			dongle_noa.option = WL_P2P_SCHED_OPTION_NORMAL;
1995 			dongle_noa.action = WL_P2P_SCHED_ACTION_RESET;
1996 		}
1997 		else {
1998 			/* Continuous NoA interval. */
1999 			dongle_noa.action = WL_P2P_SCHED_ACTION_DOZE;
2000 			dongle_noa.type = WL_P2P_SCHED_TYPE_ABS;
2001 			if ((cfg->p2p->noa.desc[0].interval == 102) ||
2002 				(cfg->p2p->noa.desc[0].interval == 100)) {
2003 				cfg->p2p->noa.desc[0].start = 100 -
2004 					cfg->p2p->noa.desc[0].duration;
2005 				dongle_noa.option = WL_P2P_SCHED_OPTION_BCNPCT;
2006 			}
2007 			else {
2008 				dongle_noa.option = WL_P2P_SCHED_OPTION_NORMAL;
2009 			}
2010 		}
2011 		/* Put the noa descriptor in dongle format for dongle */
2012 		dongle_noa.desc[0].count = htod32(cfg->p2p->noa.desc[0].count);
2013 		if (dongle_noa.option == WL_P2P_SCHED_OPTION_BCNPCT) {
2014 			dongle_noa.desc[0].start = htod32(cfg->p2p->noa.desc[0].start);
2015 			dongle_noa.desc[0].duration = htod32(cfg->p2p->noa.desc[0].duration);
2016 		}
2017 		else {
2018 			dongle_noa.desc[0].start = htod32(cfg->p2p->noa.desc[0].start*1000);
2019 			dongle_noa.desc[0].duration = htod32(cfg->p2p->noa.desc[0].duration*1000);
2020 		}
2021 		dongle_noa.desc[0].interval = htod32(cfg->p2p->noa.desc[0].interval*1000);
2022 		bssidx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
2023 		if (wl_cfgp2p_find_type(cfg, bssidx, &type) != BCME_OK)
2024 			return BCME_ERROR;
2025 
2026 		if (dongle_noa.action == WL_P2P_SCHED_ACTION_RESET) {
2027 			iovar_len -= sizeof(wl_p2p_sched_desc_t);
2028 		}
2029 
2030 		ret = wldev_iovar_setbuf(wl_to_p2p_bss_ndev(cfg, type),
2031 			"p2p_noa", &dongle_noa, iovar_len, cfg->ioctl_buf,
2032 			WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
2033 
2034 		if (ret < 0) {
2035 			CFGP2P_ERR(("fw set p2p_noa failed %d\n", ret));
2036 		}
2037 	}
2038 	else {
2039 		CFGP2P_ERR(("ERROR: set_noa in non-p2p mode\n"));
2040 	}
2041 	return ret;
2042 }
2043 s32
wl_cfgp2p_get_p2p_noa(struct bcm_cfg80211 * cfg,struct net_device * ndev,char * buf,int buf_len)2044 wl_cfgp2p_get_p2p_noa(struct bcm_cfg80211 *cfg, struct net_device *ndev, char* buf, int buf_len)
2045 {
2046 
2047 	wifi_p2p_noa_desc_t *noa_desc;
2048 	int len = 0, i;
2049 	char _buf[200];
2050 
2051 	CFGP2P_DBG((" Enter\n"));
2052 	buf[0] = '\0';
2053 	if (wl_cfgp2p_vif_created(cfg)) {
2054 		if (cfg->p2p->noa.desc[0].count || cfg->p2p->ops.ops) {
2055 			_buf[0] = 1; /* noa index */
2056 			_buf[1] = (cfg->p2p->ops.ops ? 0x80: 0) |
2057 				(cfg->p2p->ops.ctw & 0x7f); /* ops + ctw */
2058 			len += 2;
2059 			if (cfg->p2p->noa.desc[0].count) {
2060 				noa_desc = (wifi_p2p_noa_desc_t*)&_buf[len];
2061 				noa_desc->cnt_type = cfg->p2p->noa.desc[0].count;
2062 				noa_desc->duration = cfg->p2p->noa.desc[0].duration;
2063 				noa_desc->interval = cfg->p2p->noa.desc[0].interval;
2064 				noa_desc->start = cfg->p2p->noa.desc[0].start;
2065 				len += sizeof(wifi_p2p_noa_desc_t);
2066 			}
2067 			if (buf_len <= len * 2) {
2068 				CFGP2P_ERR(("ERROR: buf_len %d in not enough for"
2069 					"returning noa in string format\n", buf_len));
2070 				return -1;
2071 			}
2072 			/* We have to convert the buffer data into ASCII strings */
2073 			for (i = 0; i < len; i++) {
2074 				snprintf(buf, 3, "%02x", _buf[i]);
2075 				buf += 2;
2076 			}
2077 			buf[i*2] = '\0';
2078 		}
2079 	}
2080 	else {
2081 		CFGP2P_ERR(("ERROR: get_noa in non-p2p mode\n"));
2082 		return -1;
2083 	}
2084 	return len * 2;
2085 }
2086 s32
wl_cfgp2p_set_p2p_ps(struct bcm_cfg80211 * cfg,struct net_device * ndev,char * buf,int len)2087 wl_cfgp2p_set_p2p_ps(struct bcm_cfg80211 *cfg, struct net_device *ndev, char* buf, int len)
2088 {
2089 	int ps, ctw;
2090 	int ret = -1;
2091 	s32 legacy_ps;
2092 	s32 conn_idx;
2093 	s32 bssidx;
2094 	struct net_device *dev;
2095 
2096 	CFGP2P_DBG((" Enter\n"));
2097 	if (wl_cfgp2p_vif_created(cfg)) {
2098 		sscanf(buf, "%10d %10d %10d", &legacy_ps, &ps, &ctw);
2099 		CFGP2P_DBG((" Enter legacy_ps %d ps %d ctw %d\n", legacy_ps, ps, ctw));
2100 
2101 		bssidx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
2102 		if (wl_cfgp2p_find_type(cfg, bssidx, &conn_idx) != BCME_OK)
2103 			return BCME_ERROR;
2104 		dev = wl_to_p2p_bss_ndev(cfg, conn_idx);
2105 		if (ctw != -1) {
2106 			cfg->p2p->ops.ctw = ctw;
2107 			ret = 0;
2108 		}
2109 		if (ps != -1) {
2110 			cfg->p2p->ops.ops = ps;
2111 			ret = wldev_iovar_setbuf(dev,
2112 				"p2p_ops", &cfg->p2p->ops, sizeof(cfg->p2p->ops),
2113 				cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
2114 			if (ret < 0) {
2115 				CFGP2P_ERR(("fw set p2p_ops failed %d\n", ret));
2116 			}
2117 		}
2118 
2119 		if ((legacy_ps != -1) && ((legacy_ps == PM_MAX) || (legacy_ps == PM_OFF))) {
2120 			ret = wldev_ioctl_set(dev,
2121 				WLC_SET_PM, &legacy_ps, sizeof(legacy_ps));
2122 			if (unlikely(ret))
2123 				CFGP2P_ERR(("error (%d)\n", ret));
2124 			wl_cfg80211_update_power_mode(dev);
2125 		}
2126 		else
2127 			CFGP2P_ERR(("ilegal setting\n"));
2128 	}
2129 	else {
2130 		CFGP2P_ERR(("ERROR: set_p2p_ps in non-p2p mode\n"));
2131 		ret = -1;
2132 	}
2133 	return ret;
2134 }
2135 
2136 s32
wl_cfgp2p_set_p2p_ecsa(struct bcm_cfg80211 * cfg,struct net_device * ndev,char * buf,int len)2137 wl_cfgp2p_set_p2p_ecsa(struct bcm_cfg80211 *cfg, struct net_device *ndev, char* buf, int len)
2138 {
2139 	int ch, bw;
2140 	s32 conn_idx;
2141 	s32 bssidx;
2142 	struct net_device *dev;
2143 	char smbuf[WLC_IOCTL_SMLEN];
2144 	wl_chan_switch_t csa_arg;
2145 	u32 chnsp = 0;
2146 	int err = 0;
2147 
2148 	CFGP2P_DBG((" Enter\n"));
2149 	if (wl_cfgp2p_vif_created(cfg)) {
2150 		sscanf(buf, "%10d %10d", &ch, &bw);
2151 		CFGP2P_DBG(("Enter ch %d bw %d\n", ch, bw));
2152 
2153 		bssidx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
2154 		if (wl_cfgp2p_find_type(cfg, bssidx, &conn_idx) != BCME_OK) {
2155 			return BCME_ERROR;
2156 		}
2157 		dev = wl_to_p2p_bss_ndev(cfg, conn_idx);
2158 		if (ch <= 0 || bw <= 0) {
2159 			CFGP2P_ERR(("Negative value not permitted!\n"));
2160 			return BCME_ERROR;
2161 		}
2162 
2163 		memset_s(&csa_arg, sizeof(csa_arg), 0, sizeof(csa_arg));
2164 		csa_arg.mode = DOT11_CSA_MODE_ADVISORY;
2165 		csa_arg.count = P2P_ECSA_CNT;
2166 		csa_arg.reg = 0;
2167 
2168 		snprintf(buf, len, "%d/%d", ch, bw);
2169 		chnsp = wf_chspec_aton(buf);
2170 		if (chnsp == 0) {
2171 			CFGP2P_ERR(("%s:chsp is not correct\n", __FUNCTION__));
2172 			return BCME_ERROR;
2173 		}
2174 		chnsp = wl_chspec_host_to_driver(chnsp);
2175 		csa_arg.chspec = chnsp;
2176 
2177 		err = wldev_iovar_setbuf(dev, "csa", &csa_arg, sizeof(csa_arg),
2178 			smbuf, sizeof(smbuf), NULL);
2179 		if (err) {
2180 			CFGP2P_ERR(("%s:set p2p_ecsa failed:%d\n", __FUNCTION__, err));
2181 			return BCME_ERROR;
2182 		}
2183 	} else {
2184 		CFGP2P_ERR(("ERROR: set_p2p_ecsa in non-p2p mode\n"));
2185 		return BCME_ERROR;
2186 	}
2187 	return BCME_OK;
2188 }
2189 
2190 s32
wl_cfgp2p_increase_p2p_bw(struct bcm_cfg80211 * cfg,struct net_device * ndev,char * buf,int len)2191 wl_cfgp2p_increase_p2p_bw(struct bcm_cfg80211 *cfg, struct net_device *ndev, char* buf, int len)
2192 {
2193 	int algo;
2194 	int bw;
2195 	int ret = BCME_OK;
2196 
2197 	sscanf(buf, "%3d", &bw);
2198 	if (bw == 0) {
2199 		algo = 0;
2200 		ret = wldev_iovar_setbuf(ndev, "mchan_algo", &algo, sizeof(algo), cfg->ioctl_buf,
2201 				WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
2202 		if (ret < 0) {
2203 			CFGP2P_ERR(("fw set mchan_algo failed %d\n", ret));
2204 			return BCME_ERROR;
2205 		}
2206 	} else {
2207 		algo = 1;
2208 		ret = wldev_iovar_setbuf(ndev, "mchan_algo", &algo, sizeof(algo), cfg->ioctl_buf,
2209 				WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
2210 		if (ret < 0) {
2211 			CFGP2P_ERR(("fw set mchan_algo failed %d\n", ret));
2212 			return BCME_ERROR;
2213 		}
2214 		ret = wldev_iovar_setbuf(ndev, "mchan_bw", &bw, sizeof(algo), cfg->ioctl_buf,
2215 				WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
2216 		if (ret < 0) {
2217 			CFGP2P_ERR(("fw set mchan_bw failed %d\n", ret));
2218 			return BCME_ERROR;
2219 		}
2220 	}
2221 	return BCME_OK;
2222 }
2223 
2224 const u8 *
wl_cfgp2p_retreive_p2pattrib(const void * buf,u8 element_id)2225 wl_cfgp2p_retreive_p2pattrib(const void *buf, u8 element_id)
2226 {
2227 	const wifi_p2p_ie_t *ie = NULL;
2228 	u16 len = 0;
2229 	const u8 *subel;
2230 	u8 subelt_id;
2231 	u16 subelt_len;
2232 
2233 	if (!buf) {
2234 		WL_ERR(("P2P IE not present"));
2235 		return 0;
2236 	}
2237 
2238 	ie = (const wifi_p2p_ie_t*) buf;
2239 	len = ie->len;
2240 
2241 	/* Point subel to the P2P IE's subelt field.
2242 	 * Subtract the preceding fields (id, len, OUI, oui_type) from the length.
2243 	 */
2244 	subel = ie->subelts;
2245 	len -= 4;	/* exclude OUI + OUI_TYPE */
2246 
2247 	while (len >= 3) {
2248 		/* attribute id */
2249 		subelt_id = *subel;
2250 		subel += 1;
2251 		len -= 1;
2252 
2253 		/* 2-byte little endian */
2254 		subelt_len = *subel++;
2255 		subelt_len |= *subel++ << 8;
2256 
2257 		len -= 2;
2258 		len -= subelt_len;	/* for the remaining subelt fields */
2259 
2260 		if (subelt_id == element_id) {
2261 			/* This will point to start of subelement attrib after
2262 			 * attribute id & len
2263 			 */
2264 			return subel;
2265 		}
2266 
2267 		/* Go to next subelement */
2268 		subel += subelt_len;
2269 	}
2270 
2271 	/* Not Found */
2272 	return NULL;
2273 }
2274 
2275 #define P2P_GROUP_CAPAB_GO_BIT	0x01
2276 
2277 const u8*
wl_cfgp2p_find_attrib_in_all_p2p_Ies(const u8 * parse,u32 len,u32 attrib)2278 wl_cfgp2p_find_attrib_in_all_p2p_Ies(const u8 *parse, u32 len, u32 attrib)
2279 {
2280 	bcm_tlv_t *ie;
2281 	const u8* pAttrib;
2282 	uint ie_len;
2283 
2284 	CFGP2P_DBG(("Starting parsing parse %p attrib %d remaining len %d ", parse, attrib, len));
2285 	ie_len = len;
2286 	while ((ie = bcm_parse_tlvs(parse, ie_len, DOT11_MNG_VS_ID))) {
2287 		if (wl_cfgp2p_is_p2p_ie(ie, &parse, &ie_len) == TRUE) {
2288 			/* Have the P2p ie. Now check for attribute */
2289 			if ((pAttrib = wl_cfgp2p_retreive_p2pattrib(ie, attrib)) != NULL) {
2290 				CFGP2P_DBG(("P2P attribute %d was found at parse %p",
2291 					attrib, parse));
2292 				return pAttrib;
2293 			}
2294 			else {
2295 				/* move to next IE */
2296 				bcm_tlv_buffer_advance_past(ie, &parse, &ie_len);
2297 
2298 				CFGP2P_INFO(("P2P Attribute %d not found Moving parse"
2299 					" to %p len to %d", attrib, parse, ie_len));
2300 			}
2301 		}
2302 		else {
2303 			/* It was not p2p IE. parse will get updated automatically to next TLV */
2304 			CFGP2P_INFO(("IT was NOT P2P IE parse %p len %d", parse, ie_len));
2305 		}
2306 	}
2307 	CFGP2P_ERR(("P2P attribute %d was NOT found", attrib));
2308 	return NULL;
2309 }
2310 
2311 const u8 *
wl_cfgp2p_retreive_p2p_dev_addr(wl_bss_info_t * bi,u32 bi_length)2312 wl_cfgp2p_retreive_p2p_dev_addr(wl_bss_info_t *bi, u32 bi_length)
2313 {
2314 	const u8 *capability = NULL;
2315 	bool p2p_go	= 0;
2316 	const u8 *ptr = NULL;
2317 
2318 	if (bi->length != bi->ie_offset + bi->ie_length) {
2319 		return NULL;
2320 	}
2321 
2322 	if ((capability = wl_cfgp2p_find_attrib_in_all_p2p_Ies(((u8 *) bi) + bi->ie_offset,
2323 	bi->ie_length, P2P_SEID_P2P_INFO)) == NULL) {
2324 		WL_ERR(("P2P Capability attribute not found"));
2325 		return NULL;
2326 	}
2327 
2328 	/* Check Group capability for Group Owner bit */
2329 	p2p_go = capability[1] & P2P_GROUP_CAPAB_GO_BIT;
2330 	if (!p2p_go) {
2331 		return bi->BSSID.octet;
2332 	}
2333 
2334 	/* In probe responses, DEVICE INFO attribute will be present */
2335 	if (!(ptr = wl_cfgp2p_find_attrib_in_all_p2p_Ies(((u8 *) bi) + bi->ie_offset,
2336 	bi->ie_length,  P2P_SEID_DEV_INFO))) {
2337 		/* If DEVICE_INFO is not found, this might be a beacon frame.
2338 		 * check for DEVICE_ID in the beacon frame.
2339 		 */
2340 		ptr = wl_cfgp2p_find_attrib_in_all_p2p_Ies(((u8 *) bi) + bi->ie_offset,
2341 		bi->ie_length,  P2P_SEID_DEV_ID);
2342 	}
2343 
2344 	if (!ptr)
2345 		WL_ERR((" Both DEVICE_ID & DEVICE_INFO attribute not present in P2P IE "));
2346 
2347 	return ptr;
2348 }
2349 
2350 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
2351 static void
wl_cfgp2p_ethtool_get_drvinfo(struct net_device * net,struct ethtool_drvinfo * info)2352 wl_cfgp2p_ethtool_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info)
2353 {
2354 	snprintf(info->driver, sizeof(info->driver), "p2p");
2355 	snprintf(info->version, sizeof(info->version), "%lu", (unsigned long)(0));
2356 }
2357 
2358 struct ethtool_ops cfgp2p_ethtool_ops = {
2359 	.get_drvinfo = wl_cfgp2p_ethtool_get_drvinfo
2360 };
2361 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */
2362 
2363 #ifdef CONFIG_AP6XXX_WIFI6_HDF
hdf_cfgp2p_register_ndev(struct net_device * p2p_netdev,struct net_device * primary_netdev,struct wiphy * wiphy)2364 int hdf_cfgp2p_register_ndev(struct net_device *p2p_netdev, struct net_device *primary_netdev, struct wiphy *wiphy)
2365 {
2366 
2367     //SET_NETDEV_DEV(p2p_netdev, wiphy);
2368     WL_MSG(p2p_netdev->name, "P2P Interface Registered\n");
2369     return 0;
2370 }
2371 #endif
2372 
2373 #if defined(WL_ENABLE_P2P_IF)
2374 s32
wl_cfgp2p_register_ndev(struct bcm_cfg80211 * cfg)2375 wl_cfgp2p_register_ndev(struct bcm_cfg80211 *cfg)
2376 {
2377 	int ret = 0;
2378 	struct net_device* net = NULL;
2379 	struct wireless_dev *wdev = NULL;
2380 	uint8 temp_addr[ETHER_ADDR_LEN] = { 0x00, 0x90, 0x4c, 0x33, 0x22, 0x11 };
2381 
2382 	if (cfg->p2p_net) {
2383 		CFGP2P_ERR(("p2p_net defined already.\n"));
2384 		return -EINVAL;
2385 	}
2386 
2387 	/* Allocate etherdev, including space for private structure */
2388 	if (!(net = alloc_etherdev(sizeof(struct bcm_cfg80211 *)))) {
2389 		CFGP2P_ERR(("%s: OOM - alloc_etherdev\n", __FUNCTION__));
2390 		return -ENODEV;
2391 	}
2392 
2393 	wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
2394 	if (unlikely(!wdev)) {
2395 		WL_ERR(("Could not allocate wireless device\n"));
2396 		free_netdev(net);
2397 		return -ENOMEM;
2398 	}
2399 
2400 	strncpy(net->name, "p2p%d", sizeof(net->name) - 1);
2401 	net->name[IFNAMSIZ - 1] = '\0';
2402 
2403 	/* Copy the reference to bcm_cfg80211 */
2404 	memcpy((void *)netdev_priv(net), &cfg, sizeof(struct bcm_cfg80211 *));
2405 
2406 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31))
2407 	ASSERT(!net->open);
2408 	net->do_ioctl = wl_cfgp2p_do_ioctl;
2409 	net->hard_start_xmit = wl_cfgp2p_start_xmit;
2410 	net->open = wl_cfgp2p_if_open;
2411 	net->stop = wl_cfgp2p_if_stop;
2412 #else
2413 	ASSERT(!net->netdev_ops);
2414 	net->netdev_ops = &wl_cfgp2p_if_ops;
2415 #endif
2416 
2417 	/* Register with a dummy MAC addr */
2418 	memcpy(net->dev_addr, temp_addr, ETHER_ADDR_LEN);
2419 
2420 	wdev->wiphy = cfg->wdev->wiphy;
2421 
2422 	wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
2423 
2424 	net->ieee80211_ptr = wdev;
2425 
2426 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
2427 	net->ethtool_ops = &cfgp2p_ethtool_ops;
2428 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */
2429 
2430 	SET_NETDEV_DEV(net, wiphy_dev(wdev->wiphy));
2431 
2432 	/* Associate p2p0 network interface with new wdev */
2433 	wdev->netdev = net;
2434 
2435 	ret = register_netdev(net);
2436 	if (ret) {
2437 		CFGP2P_ERR((" register_netdevice failed (%d)\n", ret));
2438 		free_netdev(net);
2439 		kfree(wdev);
2440 		return -ENODEV;
2441 	}
2442 
2443 	/* store p2p net ptr for further reference. Note that iflist won't have this
2444 	 * entry as there corresponding firmware interface is a "Hidden" interface.
2445 	 */
2446 	cfg->p2p_wdev = wdev;
2447 	cfg->p2p_net = net;
2448 
2449 	WL_MSG(net->name, "P2P Interface Registered\n");
2450 
2451 	return ret;
2452 }
2453 
2454 s32
wl_cfgp2p_unregister_ndev(struct bcm_cfg80211 * cfg)2455 wl_cfgp2p_unregister_ndev(struct bcm_cfg80211 *cfg)
2456 {
2457 
2458 	if (!cfg || !cfg->p2p_net) {
2459 		CFGP2P_ERR(("Invalid Ptr\n"));
2460 		return -EINVAL;
2461 	}
2462 
2463 	unregister_netdev(cfg->p2p_net);
2464 	free_netdev(cfg->p2p_net);
2465 
2466 	return 0;
2467 }
wl_cfgp2p_start_xmit(struct sk_buff * skb,struct net_device * ndev)2468 static netdev_tx_t wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev)
2469 {
2470 
2471 	if (skb)
2472 	{
2473 		CFGP2P_DBG(("(%s) is not used for data operations.Droping the packet.\n",
2474 			ndev->name));
2475 		dev_kfree_skb_any(skb);
2476 	}
2477 
2478 	return 0;
2479 }
2480 
wl_cfgp2p_do_ioctl(struct net_device * net,struct ifreq * ifr,int cmd)2481 static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd)
2482 {
2483 	int ret = 0;
2484 	struct bcm_cfg80211 *cfg = *(struct bcm_cfg80211 **)netdev_priv(net);
2485 	struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
2486 
2487 	/* There is no ifidx corresponding to p2p0 in our firmware. So we should
2488 	 * not Handle any IOCTL cmds on p2p0 other than ANDROID PRIVATE CMDs.
2489 	 * For Android PRIV CMD handling map it to primary I/F
2490 	 */
2491 	if (cmd == SIOCDEVPRIVATE+1) {
2492 		ret = wl_android_priv_cmd(ndev, ifr);
2493 
2494 	} else {
2495 		CFGP2P_ERR(("%s: IOCTL req 0x%x on p2p0 I/F. Ignoring. \n",
2496 		__FUNCTION__, cmd));
2497 		return -1;
2498 	}
2499 
2500 	return ret;
2501 }
2502 #endif
2503 
2504 #if defined(WL_ENABLE_P2P_IF)
wl_cfgp2p_if_open(struct net_device * net)2505 static int wl_cfgp2p_if_open(struct net_device *net)
2506 {
2507 	struct wireless_dev *wdev = net->ieee80211_ptr;
2508 
2509 	if (!wdev || !wl_cfg80211_is_p2p_active(net))
2510 		return -EINVAL;
2511 	WL_TRACE(("Enter\n"));
2512 #if !defined(WL_IFACE_COMB_NUM_CHANNELS)
2513 	/* If suppose F/W download (ifconfig wlan0 up) hasn't been done by now,
2514 	 * do it here. This will make sure that in concurrent mode, supplicant
2515 	 * is not dependent on a particular order of interface initialization.
2516 	 * i.e you may give wpa_supp -iwlan0 -N -ip2p0 or wpa_supp -ip2p0 -N
2517 	 * -iwlan0.
2518 	 */
2519 	wdev->wiphy->interface_modes |= (BIT(NL80211_IFTYPE_P2P_CLIENT)
2520 		| BIT(NL80211_IFTYPE_P2P_GO));
2521 #endif /* !WL_IFACE_COMB_NUM_CHANNELS */
2522 	wl_cfg80211_do_driver_init(net);
2523 
2524 	return 0;
2525 }
2526 
wl_cfgp2p_if_stop(struct net_device * net)2527 static int wl_cfgp2p_if_stop(struct net_device *net)
2528 {
2529 	struct wireless_dev *wdev = net->ieee80211_ptr;
2530 	struct bcm_cfg80211 *cfg = wl_get_cfg(net);
2531 
2532 	if (!wdev)
2533 		return -EINVAL;
2534 
2535 	wl_cfg80211_scan_stop(cfg, net);
2536 
2537 #if !defined(WL_IFACE_COMB_NUM_CHANNELS)
2538 	wdev->wiphy->interface_modes = (wdev->wiphy->interface_modes)
2539 					& (~(BIT(NL80211_IFTYPE_P2P_CLIENT)|
2540 					BIT(NL80211_IFTYPE_P2P_GO)));
2541 #endif /* !WL_IFACE_COMB_NUM_CHANNELS */
2542 	return 0;
2543 }
2544 
wl_cfgp2p_is_ifops(const struct net_device_ops * if_ops)2545 bool wl_cfgp2p_is_ifops(const struct net_device_ops *if_ops)
2546 {
2547 	return (if_ops == &wl_cfgp2p_if_ops);
2548 }
2549 #endif /* WL_ENABLE_P2P_IF */
2550 
2551 #if defined(WL_CFG80211_P2P_DEV_IF)
2552 struct wireless_dev *
wl_cfgp2p_add_p2p_disc_if(struct bcm_cfg80211 * cfg)2553 wl_cfgp2p_add_p2p_disc_if(struct bcm_cfg80211 *cfg)
2554 {
2555 	struct wireless_dev *wdev = NULL;
2556 	struct ether_addr primary_mac;
2557 
2558 	if (!cfg || !cfg->p2p_supported)
2559 		return ERR_PTR(-EINVAL);
2560 
2561 	printk(KERN_INFO"Enter wl_cfgp2p_add_p2p_disc_if, p2p_wdev=%p\n", cfg->p2p_wdev);
2562 
2563 	if (cfg->p2p_wdev) {
2564 #ifndef EXPLICIT_DISCIF_CLEANUP
2565 		dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
2566 #endif /* EXPLICIT_DISCIF_CLEANUP */
2567 		/*
2568 		 * This is not expected. This can happen due to
2569 		 * supplicant crash/unclean de-initialization which
2570 		 * didn't free the p2p discovery interface. Indicate
2571 		 * driver hang to user space so that the framework
2572 		 * can rei-init the Wi-Fi.
2573 		 */
2574 		CFGP2P_ERR(("p2p_wdev defined already.\n"));
2575 		wl_probe_wdev_all(cfg);
2576 #ifdef EXPLICIT_DISCIF_CLEANUP
2577 		/*
2578 		 * CUSTOMER_HW4 design doesn't delete the p2p discovery
2579 		 * interface on ifconfig wlan0 down context which comes
2580 		 * without a preceeding NL80211_CMD_DEL_INTERFACE for p2p
2581 		 * discovery. But during supplicant crash the DEL_IFACE
2582 		 * command will not happen and will cause a left over iface
2583 		 * even after ifconfig wlan0 down. So delete the iface
2584 		 * first and then indicate the HANG event
2585 		 */
2586 		wl_cfgp2p_del_p2p_disc_if(cfg->p2p_wdev, cfg);
2587 #else
2588 		dhd->hang_reason = HANG_REASON_IFACE_DEL_FAILURE;
2589 #if defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
2590 		if (dhd->memdump_enabled) {
2591 			/* Load the dongle side dump to host
2592 			 * memory and then BUG_ON()
2593 			 */
2594 			dhd->memdump_type = DUMP_TYPE_IFACE_OP_FAILURE;
2595 			dhd_bus_mem_dump(dhd);
2596 		}
2597 #endif /* BCMPCIE && DHD_FW_COREDUMP */
2598 		net_os_send_hang_message(bcmcfg_to_prmry_ndev(cfg));
2599 		return ERR_PTR(-ENODEV);
2600 #endif /* EXPLICIT_DISCIF_CLEANUP */
2601 	}
2602 
2603 	wdev = (struct wireless_dev *)MALLOCZ(cfg->osh, sizeof(*wdev));
2604 	if (unlikely(!wdev)) {
2605 		WL_ERR(("Could not allocate wireless device\n"));
2606 		return ERR_PTR(-ENOMEM);
2607 	}
2608 
2609 	bzero(&primary_mac, sizeof(primary_mac));
2610 	get_primary_mac(cfg, &primary_mac);
2611 #ifndef WL_P2P_USE_RANDMAC
2612 	wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
2613 #endif /* WL_P2P_USE_RANDMAC */
2614 
2615 	wdev->wiphy = cfg->wdev->wiphy;
2616 	wdev->iftype = NL80211_IFTYPE_P2P_DEVICE;
2617 	memcpy(wdev->address, wl_to_p2p_bss_macaddr(cfg, P2PAPI_BSSCFG_DEVICE), ETHER_ADDR_LEN);
2618 
2619 	/* store p2p wdev ptr for further reference. */
2620 	cfg->p2p_wdev = wdev;
2621 
2622 	printf("P2P interface registered, wdev mac = %02x:%02x:%02x:%02x:%02x:%02x\n", wdev->address[0], wdev->address[1],
2623         wdev->address[2], wdev->address[3], wdev->address[4], wdev->address[5]);
2624 	printf("%s: wdev: %p, wdev->net: %p\n", __FUNCTION__, wdev, wdev->netdev);
2625 #ifndef CONFIG_AP6XXX_WIFI6_HDF
2626 	magiclink_add_p2p("p2p0", wl_to_p2p_bss_macaddr(cfg, P2PAPI_BSSCFG_DEVICE), &p2p_debug_ndev);
2627 #endif
2628 	return wdev;
2629 }
2630 
2631 int
wl_cfgp2p_start_p2p_device(struct wiphy * wiphy,struct wireless_dev * wdev)2632 wl_cfgp2p_start_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev)
2633 {
2634 	int ret = 0;
2635 	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
2636 
2637 	if (!cfg)
2638 		return -EINVAL;
2639 
2640 	WL_TRACE(("Enter\n"));
2641 
2642 	ret = wl_cfgp2p_set_firm_p2p(cfg);
2643 	if (unlikely(ret < 0)) {
2644 		CFGP2P_ERR(("Set P2P in firmware failed, ret=%d\n", ret));
2645 		goto exit;
2646 	}
2647 
2648 	ret = wl_cfgp2p_enable_discovery(cfg, bcmcfg_to_prmry_ndev(cfg), NULL, 0);
2649 	if (unlikely(ret < 0)) {
2650 		CFGP2P_ERR(("P2P enable discovery failed, ret=%d\n", ret));
2651 		goto exit;
2652 	}
2653 
2654 	p2p_on(cfg) = true;
2655 #if defined(P2P_IE_MISSING_FIX)
2656 	cfg->p2p_prb_noti = false;
2657 #endif // endif
2658 
2659 	CFGP2P_DBG(("P2P interface started\n"));
2660 
2661 exit:
2662 	return ret;
2663 }
2664 
2665 void
wl_cfgp2p_stop_p2p_device(struct wiphy * wiphy,struct wireless_dev * wdev)2666 wl_cfgp2p_stop_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev)
2667 {
2668 	int ret = 0;
2669 	struct net_device *ndev = NULL;
2670 	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
2671 
2672 	if (!cfg)
2673 		return;
2674 
2675 	CFGP2P_DBG(("Enter\n"));
2676 
2677 	/* Check if cfg80211 interface is already down */
2678 	ndev = bcmcfg_to_prmry_ndev(cfg);
2679 	if (!wl_get_drv_status(cfg, READY, ndev)) {
2680 		WL_DBG(("cfg80211 interface is already down\n"));
2681 		return;	/* it is even not ready */
2682 	}
2683 
2684 	ret = wl_cfg80211_scan_stop(cfg, wdev);
2685 	if (unlikely(ret < 0)) {
2686 		CFGP2P_ERR(("P2P scan stop failed, ret=%d\n", ret));
2687 	}
2688 
2689 	if (!p2p_is_on(cfg)) {
2690 		return;
2691 	}
2692 
2693 #ifdef P2P_LISTEN_OFFLOADING
2694 	wl_cfg80211_p2plo_deinit(cfg);
2695 #endif /* P2P_LISTEN_OFFLOADING */
2696 
2697 	/* Cancel any on-going listen */
2698 	wl_cfgp2p_cancel_listen(cfg, bcmcfg_to_prmry_ndev(cfg), wdev, TRUE);
2699 
2700 	ret = wl_cfgp2p_disable_discovery(cfg);
2701 	if (unlikely(ret < 0)) {
2702 		CFGP2P_ERR(("P2P disable discovery failed, ret=%d\n", ret));
2703 	}
2704 
2705 	p2p_on(cfg) = false;
2706 
2707 	CFGP2P_DBG(("Exit. P2P interface stopped\n"));
2708 
2709 	return;
2710 }
2711 
2712 int
wl_cfgp2p_del_p2p_disc_if(struct wireless_dev * wdev,struct bcm_cfg80211 * cfg)2713 wl_cfgp2p_del_p2p_disc_if(struct wireless_dev *wdev, struct bcm_cfg80211 *cfg)
2714 {
2715 	bool rollback_lock = false;
2716 
2717 	if (!wdev || !cfg) {
2718 		WL_ERR(("wdev or cfg is NULL\n"));
2719 		return -EINVAL;
2720 	}
2721 
2722 	printk(KERN_INFO"Enter wl_cfgp2p_del_p2p_disc_if wdev->netdev=%p %d\n", wdev->netdev, wdev->iftype);
2723 
2724 	if (!cfg->p2p_wdev) {
2725 		WL_ERR(("Already deleted p2p_wdev\n"));
2726 		return -EINVAL;
2727 	}
2728 
2729 	if (!rtnl_is_locked()) {
2730 		rtnl_lock();
2731 		rollback_lock = true;
2732 	}
2733 
2734 #ifndef CONFIG_AP6XXX_WIFI6_HDF
2735 	cfg80211_unregister_wdev(wdev);
2736 #endif
2737 
2738 	if (rollback_lock)
2739 		rtnl_unlock();
2740 
2741 	synchronize_rcu();
2742 
2743 	MFREE(cfg->osh, wdev, sizeof(*wdev));
2744 
2745 	cfg->p2p_wdev = NULL;
2746 
2747 	CFGP2P_ERR(("P2P interface unregistered\n"));
2748 #ifndef CONFIG_AP6XXX_WIFI6_HDF
2749 	if (p2p_debug_ndev != NULL)
2750 		dhd_del_monitor(p2p_debug_ndev);
2751 #endif
2752 	return 0;
2753 }
2754 #endif /* WL_CFG80211_P2P_DEV_IF */
2755 
2756 void
wl_cfgp2p_need_wait_actfrmae(struct bcm_cfg80211 * cfg,void * frame,u32 frame_len,bool tx)2757 wl_cfgp2p_need_wait_actfrmae(struct bcm_cfg80211 *cfg, void *frame, u32 frame_len, bool tx)
2758 {
2759 	wifi_p2p_pub_act_frame_t *pact_frm;
2760 	int status = 0;
2761 
2762 	if (!frame || (frame_len < (sizeof(*pact_frm) + WL_P2P_AF_STATUS_OFFSET - 1))) {
2763 		return;
2764 	}
2765 
2766 	if (wl_cfgp2p_is_pub_action(frame, frame_len)) {
2767 		pact_frm = (wifi_p2p_pub_act_frame_t *)frame;
2768 		if (pact_frm->subtype == P2P_PAF_GON_RSP && tx) {
2769 			CFGP2P_ACTION(("Check TX P2P Group Owner Negotiation Rsp Frame status\n"));
2770 			status = pact_frm->elts[WL_P2P_AF_STATUS_OFFSET];
2771 			if (status) {
2772 				cfg->need_wait_afrx = false;
2773 				return;
2774 			}
2775 		}
2776 	}
2777 
2778 	cfg->need_wait_afrx = true;
2779 	return;
2780 }
2781 
2782 int
wl_cfgp2p_is_p2p_specific_scan(struct cfg80211_scan_request * request)2783 wl_cfgp2p_is_p2p_specific_scan(struct cfg80211_scan_request *request)
2784 {
2785 	if (request && (request->n_ssids == 1) &&
2786 		(request->n_channels == 1) &&
2787 		IS_P2P_SSID(request->ssids[0].ssid, WL_P2P_WILDCARD_SSID_LEN) &&
2788 		(request->ssids[0].ssid_len > WL_P2P_WILDCARD_SSID_LEN)) {
2789 		return true;
2790 	}
2791 	return false;
2792 }
2793