2 * Linux cfg80211 Vendor Extension Code
4 * Copyright (C) 1999-2019, Broadcom.
6 * Unless you and Broadcom execute a separate written software license
7 * agreement governing use of this software, this software is licensed to you
8 * under the terms of the GNU General Public License version 2 (the "GPL"),
9 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
10 * following added to such license:
12 * As a special exception, the copyright holders of this software give you
13 * permission to link this software with independent modules, and to copy and
14 * distribute the resulting executable under terms of your choice, provided that
15 * you also meet, for each linked independent module, the terms and conditions of
16 * the license of that module. An independent module is a module which is not
17 * derived from this software. The special exception does not apply to any
18 * modifications of the software.
20 * Notwithstanding the above, under no circumstances may you combine this
21 * software in any way with any other Broadcom software provided under a license
22 * other than the GPL, without Broadcom's express prior written consent.
25 * <<Broadcom-WL-IPTag/Open:>>
27 * $Id: wl_cfgvendor.c 797501 2019-01-02 04:57:12Z $
31 * New vendor interface additon to nl80211/cfg80211 to allow vendors
32 * to implement proprietary features over the cfg80211 stack.
38 #include <linux/kernel.h>
39 #include <linux/vmalloc.h>
42 #include <bcmwifi_channels.h>
43 #include <bcmendian.h>
46 #include <linux/if_arp.h>
47 #include <asm/uaccess.h>
49 #include <dngl_stats.h>
51 #include <dhd_debug.h>
54 #include <wlioctl_utils.h>
55 #include <dhd_cfg80211.h>
58 #endif /* PNO_SUPPORT */
61 #endif /* RTT_SUPPORT */
64 #include <linux/kernel.h>
65 #include <linux/kthread.h>
66 #include <linux/netdevice.h>
67 #include <linux/sched.h>
68 #include <linux/etherdevice.h>
69 #include <linux/wireless.h>
70 #include <linux/ieee80211.h>
71 #include <linux/wait.h>
72 #include <net/cfg80211.h>
73 #include <net/rtnetlink.h>
76 #include <wldev_common.h>
77 #include <wl_cfg80211.h>
78 #include <wl_cfgp2p.h>
80 #include <wl_cfgnan.h>
82 #include <wl_android.h>
83 #include <wl_cfgvendor.h>
87 #include <brcm_nl80211.h>
90 wl_get_kernel_timestamp(void)
94 unsigned long rem_nsec
;
96 ts_nsec
= local_clock();
97 rem_nsec
= DIV_AND_MOD_U64_BY_U32(ts_nsec
, NSEC_PER_SEC
);
98 snprintf(buf
, sizeof(buf
), "%5lu.%06lu",
99 (unsigned long)ts_nsec
, rem_nsec
/ NSEC_PER_USEC
);
104 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
105 #if defined(WL_SUPP_EVENT)
107 wl_cfgvendor_send_supp_eventstring(const char *func_name
, const char *fmt
, ...)
109 char buf
[SUPP_LOG_LEN
] = {0};
110 struct bcm_cfg80211
*cfg
;
117 cfg
= wl_cfg80211_get_bcmcfg();
118 if (!cfg
|| !cfg
->wdev
) {
119 WL_DBG(("supp evt invalid arg\n"));
123 wiphy
= cfg
->wdev
->wiphy
;
124 prefix_len
= snprintf(buf
, SUPP_LOG_LEN
, "[DHD]<%s> %s: ",
125 wl_get_kernel_timestamp(), __func__
);
126 /* Remaining buffer len */
127 rem_len
= SUPP_LOG_LEN
- (prefix_len
+ 1);
128 /* Print the arg list on to the remaining part of the buffer */
130 len
= vsnprintf((buf
+ prefix_len
), rem_len
, fmt
, args
);
137 /* If return length is greater than buffer len,
138 * then its truncated buffer case.
143 /* Ensure the buffer is null terminated */
148 return wl_cfgvendor_send_async_event(wiphy
,
149 bcmcfg_to_prmry_ndev(cfg
), BRCM_VENDOR_EVENT_PRIV_STR
, buf
, len
);
151 #endif /* WL_SUPP_EVENT */
154 * This API is to be used for asynchronous vendor events. This
155 * shouldn't be used in response to a vendor command from its
156 * do_it handler context (instead wl_cfgvendor_send_cmd_reply should
159 int wl_cfgvendor_send_async_event(struct wiphy
*wiphy
,
160 struct net_device
*dev
, int event_id
, const void *data
, int len
)
165 kflags
= in_atomic() ? GFP_ATOMIC
: GFP_KERNEL
;
167 /* Alloc the SKB for vendor_event */
168 #if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
169 LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
170 skb
= cfg80211_vendor_event_alloc(wiphy
, ndev_to_wdev(dev
), len
, event_id
, kflags
);
172 skb
= cfg80211_vendor_event_alloc(wiphy
, len
, event_id
, kflags
);
173 #endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
174 /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */
176 WL_ERR(("skb alloc failed"));
180 /* Push the data to the skb */
181 nla_put_nohdr(skb
, len
, data
);
183 cfg80211_vendor_event(skb
, kflags
);
189 wl_cfgvendor_send_cmd_reply(struct wiphy
*wiphy
,
190 const void *data
, int len
)
195 /* Alloc the SKB for vendor_event */
196 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, len
);
197 if (unlikely(!skb
)) {
198 WL_ERR(("skb alloc failed"));
203 /* Push the data to the skb */
204 nla_put_nohdr(skb
, len
, data
);
205 err
= cfg80211_vendor_cmd_reply(skb
);
207 WL_DBG(("wl_cfgvendor_send_cmd_reply status %d", err
));
212 wl_cfgvendor_get_feature_set(struct wiphy
*wiphy
,
213 struct wireless_dev
*wdev
, const void *data
, int len
)
216 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
219 reply
= dhd_dev_get_feature_set(bcmcfg_to_prmry_ndev(cfg
));
221 err
= wl_cfgvendor_send_cmd_reply(wiphy
, &reply
, sizeof(int));
223 WL_ERR(("Vendor Command reply failed ret:%d \n", err
));
229 wl_cfgvendor_get_feature_set_matrix(struct wiphy
*wiphy
,
230 struct wireless_dev
*wdev
, const void *data
, int len
)
233 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
238 mem_needed
= VENDOR_REPLY_OVERHEAD
+
239 (ATTRIBUTE_U32_LEN
* MAX_FEATURE_SET_CONCURRRENT_GROUPS
) + ATTRIBUTE_U32_LEN
;
241 /* Alloc the SKB for vendor_event */
242 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, mem_needed
);
243 if (unlikely(!skb
)) {
244 WL_ERR(("skb alloc failed"));
249 nla_put_u32(skb
, ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET
, MAX_FEATURE_SET_CONCURRRENT_GROUPS
);
250 for (i
= 0; i
< MAX_FEATURE_SET_CONCURRRENT_GROUPS
; i
++) {
251 reply
= dhd_dev_get_feature_set_matrix(bcmcfg_to_prmry_ndev(cfg
), i
);
252 if (reply
!= WIFI_FEATURE_INVALID
) {
253 nla_put_u32(skb
, ANDR_WIFI_ATTRIBUTE_FEATURE_SET
, reply
);
257 err
= cfg80211_vendor_cmd_reply(skb
);
260 WL_ERR(("Vendor Command reply failed ret:%d \n", err
));
267 wl_cfgvendor_set_rand_mac_oui(struct wiphy
*wiphy
,
268 struct wireless_dev
*wdev
, const void *data
, int len
)
271 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
274 type
= nla_type(data
);
276 if (type
== ANDR_WIFI_ATTRIBUTE_RANDOM_MAC_OUI
) {
277 if (nla_len(data
) != DOT11_OUI_LEN
) {
278 WL_ERR(("nla_len not matched.\n"));
282 err
= dhd_dev_cfg_rand_mac_oui(bcmcfg_to_prmry_ndev(cfg
), nla_data(data
));
285 WL_ERR(("Bad OUI, could not set:%d \n", err
));
293 #ifdef CUSTOM_FORCE_NODFS_FLAG
295 wl_cfgvendor_set_nodfs_flag(struct wiphy
*wiphy
,
296 struct wireless_dev
*wdev
, const void *data
, int len
)
299 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
303 type
= nla_type(data
);
304 if (type
== ANDR_WIFI_ATTRIBUTE_NODFS_SET
) {
305 nodfs
= nla_get_u32(data
);
306 err
= dhd_dev_set_nodfs(bcmcfg_to_prmry_ndev(cfg
), nodfs
);
312 #endif /* CUSTOM_FORCE_NODFS_FLAG */
315 wl_cfgvendor_set_country(struct wiphy
*wiphy
,
316 struct wireless_dev
*wdev
, const void *data
, int len
)
318 int err
= BCME_ERROR
, rem
, type
;
319 char country_code
[WLC_CNTRY_BUF_SZ
] = {0};
320 const struct nlattr
*iter
;
321 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
322 struct net_device
*primary_ndev
= bcmcfg_to_prmry_ndev(cfg
);
324 nla_for_each_attr(iter
, data
, len
, rem
) {
325 type
= nla_type(iter
);
327 case ANDR_WIFI_ATTRIBUTE_COUNTRY
:
328 memcpy(country_code
, nla_data(iter
),
329 MIN(nla_len(iter
), WLC_CNTRY_BUF_SZ
));
332 WL_ERR(("Unknown type: %d\n", type
));
337 /* country code is unique for dongle..hence using primary interface. */
338 err
= wldev_set_country(primary_ndev
, country_code
, true, true, -1);
340 WL_ERR(("Set country failed ret:%d\n", err
));
348 wl_cfgvendor_send_hotlist_event(struct wiphy
*wiphy
,
349 struct net_device
*dev
, void *data
, int len
, wl_vendor_event_t event
)
354 int malloc_len
, total
, iter_cnt_to_send
, cnt
;
355 gscan_results_cache_t
*cache
= (gscan_results_cache_t
*)data
;
357 total
= len
/sizeof(wifi_gscan_result_t
);
359 malloc_len
= (total
* sizeof(wifi_gscan_result_t
)) + VENDOR_DATA_OVERHEAD
;
360 if (malloc_len
> NLMSG_DEFAULT_SIZE
) {
361 malloc_len
= NLMSG_DEFAULT_SIZE
;
364 (malloc_len
- VENDOR_DATA_OVERHEAD
)/sizeof(wifi_gscan_result_t
);
365 total
= total
- iter_cnt_to_send
;
367 kflags
= in_atomic() ? GFP_ATOMIC
: GFP_KERNEL
;
369 /* Alloc the SKB for vendor_event */
370 #if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
371 LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
372 skb
= cfg80211_vendor_event_alloc(wiphy
, ndev_to_wdev(dev
),
373 malloc_len
, event
, kflags
);
375 skb
= cfg80211_vendor_event_alloc(wiphy
, malloc_len
, event
, kflags
);
376 #endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
377 /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */
379 WL_ERR(("skb alloc failed"));
383 while (cache
&& iter_cnt_to_send
) {
384 ptr
= (const void *) &cache
->results
[cache
->tot_consumed
];
386 if (iter_cnt_to_send
< (cache
->tot_count
- cache
->tot_consumed
)) {
387 cnt
= iter_cnt_to_send
;
389 cnt
= (cache
->tot_count
- cache
->tot_consumed
);
392 iter_cnt_to_send
-= cnt
;
393 cache
->tot_consumed
+= cnt
;
394 /* Push the data to the skb */
395 nla_append(skb
, cnt
* sizeof(wifi_gscan_result_t
), ptr
);
396 if (cache
->tot_consumed
== cache
->tot_count
) {
402 cfg80211_vendor_event(skb
, kflags
);
409 wl_cfgvendor_gscan_get_capabilities(struct wiphy
*wiphy
,
410 struct wireless_dev
*wdev
, const void *data
, int len
)
413 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
414 dhd_pno_gscan_capabilities_t
*reply
= NULL
;
415 uint32 reply_len
= 0;
417 reply
= dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg
),
418 DHD_PNO_GET_CAPABILITIES
, NULL
, &reply_len
);
420 WL_ERR(("Could not get capabilities\n"));
425 err
= wl_cfgvendor_send_cmd_reply(wiphy
, reply
, reply_len
);
428 WL_ERR(("Vendor Command reply failed ret:%d \n", err
));
431 MFREE(cfg
->osh
, reply
, reply_len
);
436 wl_cfgvendor_gscan_get_batch_results(struct wiphy
*wiphy
,
437 struct wireless_dev
*wdev
, const void *data
, int len
)
440 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
441 gscan_results_cache_t
*results
, *iter
;
442 uint32 reply_len
, is_done
= 1;
443 int32 mem_needed
, num_results_iter
;
444 wifi_gscan_result_t
*ptr
;
445 uint16 num_scan_ids
, num_results
;
447 struct nlattr
*scan_hdr
, *complete_flag
;
449 err
= dhd_dev_wait_batch_results_complete(bcmcfg_to_prmry_ndev(cfg
));
453 err
= dhd_dev_pno_lock_access_batch_results(bcmcfg_to_prmry_ndev(cfg
));
454 if (err
!= BCME_OK
) {
455 WL_ERR(("Can't obtain lock to access batch results %d\n", err
));
458 results
= dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg
),
459 DHD_PNO_GET_BATCH_RESULTS
, NULL
, &reply_len
);
461 WL_ERR(("No results to send %d\n", err
));
462 err
= wl_cfgvendor_send_cmd_reply(wiphy
, results
, 0);
465 WL_ERR(("Vendor Command reply failed ret:%d \n", err
));
466 dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg
));
469 num_scan_ids
= reply_len
& 0xFFFF;
470 num_results
= (reply_len
& 0xFFFF0000) >> 16;
471 mem_needed
= (num_results
* sizeof(wifi_gscan_result_t
)) +
472 (num_scan_ids
* GSCAN_BATCH_RESULT_HDR_LEN
) +
473 VENDOR_REPLY_OVERHEAD
+ SCAN_RESULTS_COMPLETE_FLAG_LEN
;
475 if (mem_needed
> (int32
)NLMSG_DEFAULT_SIZE
) {
476 mem_needed
= (int32
)NLMSG_DEFAULT_SIZE
;
479 WL_TRACE(("is_done %d mem_needed %d max_mem %d\n", is_done
, mem_needed
,
480 (int)NLMSG_DEFAULT_SIZE
));
481 /* Alloc the SKB for vendor_event */
482 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, mem_needed
);
483 if (unlikely(!skb
)) {
484 WL_ERR(("skb alloc failed"));
485 dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg
));
489 complete_flag
= nla_reserve(skb
, GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE
,
491 mem_needed
= mem_needed
- (SCAN_RESULTS_COMPLETE_FLAG_LEN
+ VENDOR_REPLY_OVERHEAD
);
494 num_results_iter
= (mem_needed
- (int32
)GSCAN_BATCH_RESULT_HDR_LEN
);
495 num_results_iter
/= (int32
)sizeof(wifi_gscan_result_t
);
496 if (num_results_iter
<= 0 ||
497 ((iter
->tot_count
- iter
->tot_consumed
) > num_results_iter
)) {
500 scan_hdr
= nla_nest_start(skb
, GSCAN_ATTRIBUTE_SCAN_RESULTS
);
501 /* no more room? we are done then (for now) */
502 if (scan_hdr
== NULL
) {
506 nla_put_u32(skb
, GSCAN_ATTRIBUTE_SCAN_ID
, iter
->scan_id
);
507 nla_put_u8(skb
, GSCAN_ATTRIBUTE_SCAN_FLAGS
, iter
->flag
);
508 nla_put_u32(skb
, GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK
, iter
->scan_ch_bucket
);
510 num_results_iter
= iter
->tot_count
- iter
->tot_consumed
;
512 nla_put_u32(skb
, GSCAN_ATTRIBUTE_NUM_OF_RESULTS
, num_results_iter
);
513 if (num_results_iter
) {
514 ptr
= &iter
->results
[iter
->tot_consumed
];
515 iter
->tot_consumed
+= num_results_iter
;
516 nla_put(skb
, GSCAN_ATTRIBUTE_SCAN_RESULTS
,
517 num_results_iter
* sizeof(wifi_gscan_result_t
), ptr
);
519 nla_nest_end(skb
, scan_hdr
);
520 mem_needed
-= GSCAN_BATCH_RESULT_HDR_LEN
+
521 (num_results_iter
* sizeof(wifi_gscan_result_t
));
524 MFREE(cfg
->osh
, results
, reply_len
);
525 /* Returns TRUE if all result consumed */
526 is_done
= dhd_dev_gscan_batch_cache_cleanup(bcmcfg_to_prmry_ndev(cfg
));
527 memcpy(nla_data(complete_flag
), &is_done
, sizeof(is_done
));
528 dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg
));
529 return cfg80211_vendor_cmd_reply(skb
);
533 wl_cfgvendor_initiate_gscan(struct wiphy
*wiphy
,
534 struct wireless_dev
*wdev
, const void *data
, int len
)
537 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
541 const struct nlattr
*iter
;
543 nla_for_each_attr(iter
, data
, len
, tmp
) {
544 type
= nla_type(iter
);
545 if (type
== GSCAN_ATTRIBUTE_ENABLE_FEATURE
)
546 run
= nla_get_u32(iter
);
547 else if (type
== GSCAN_ATTRIBUTE_FLUSH_FEATURE
)
548 flush
= nla_get_u32(iter
);
552 err
= dhd_dev_pno_run_gscan(bcmcfg_to_prmry_ndev(cfg
), run
, flush
);
555 WL_ERR(("Could not run gscan:%d \n", err
));
565 wl_cfgvendor_enable_full_scan_result(struct wiphy
*wiphy
,
566 struct wireless_dev
*wdev
, const void *data
, int len
)
569 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
571 bool real_time
= FALSE
;
573 type
= nla_type(data
);
575 if (type
== GSCAN_ATTRIBUTE_ENABLE_FULL_SCAN_RESULTS
) {
576 real_time
= nla_get_u32(data
);
578 err
= dhd_dev_pno_enable_full_scan_result(bcmcfg_to_prmry_ndev(cfg
), real_time
);
581 WL_ERR(("Could not run gscan:%d \n", err
));
592 wl_cfgvendor_set_scan_cfg_bucket(const struct nlattr
*prev
,
593 gscan_scan_params_t
*scan_param
, int num
)
595 struct dhd_pno_gscan_channel_bucket
*ch_bucket
;
597 int type
, err
= 0, rem
;
598 const struct nlattr
*cur
, *next
;
600 nla_for_each_nested(cur
, prev
, rem
) {
601 type
= nla_type(cur
);
602 ch_bucket
= scan_param
->channel_bucket
;
604 case GSCAN_ATTRIBUTE_BUCKET_ID
:
606 case GSCAN_ATTRIBUTE_BUCKET_PERIOD
:
607 if (nla_len(cur
) != sizeof(uint32
)) {
612 ch_bucket
[num
].bucket_freq_multiple
=
613 nla_get_u32(cur
) / MSEC_PER_SEC
;
615 case GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS
:
616 if (nla_len(cur
) != sizeof(uint32
)) {
620 ch_bucket
[num
].num_channels
= nla_get_u32(cur
);
621 if (ch_bucket
[num
].num_channels
>
622 GSCAN_MAX_CHANNELS_IN_BUCKET
) {
623 WL_ERR(("channel range:%d,bucket:%d\n",
624 ch_bucket
[num
].num_channels
,
630 case GSCAN_ATTRIBUTE_BUCKET_CHANNELS
:
631 nla_for_each_nested(next
, cur
, rem
) {
632 if (k
>= GSCAN_MAX_CHANNELS_IN_BUCKET
)
634 if (nla_len(next
) != sizeof(uint32
)) {
638 ch_bucket
[num
].chan_list
[k
] = nla_get_u32(next
);
642 case GSCAN_ATTRIBUTE_BUCKETS_BAND
:
643 if (nla_len(cur
) != sizeof(uint32
)) {
647 ch_bucket
[num
].band
= (uint16
)nla_get_u32(cur
);
649 case GSCAN_ATTRIBUTE_REPORT_EVENTS
:
650 if (nla_len(cur
) != sizeof(uint32
)) {
654 ch_bucket
[num
].report_flag
= (uint8
)nla_get_u32(cur
);
656 case GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT
:
657 if (nla_len(cur
) != sizeof(uint32
)) {
661 ch_bucket
[num
].repeat
= (uint16
)nla_get_u32(cur
);
663 case GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD
:
664 if (nla_len(cur
) != sizeof(uint32
)) {
668 ch_bucket
[num
].bucket_max_multiple
=
669 nla_get_u32(cur
) / MSEC_PER_SEC
;
672 WL_ERR(("unknown attr type:%d\n", type
));
683 wl_cfgvendor_set_scan_cfg(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
684 const void *data
, int len
)
687 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
688 gscan_scan_params_t
*scan_param
;
691 const struct nlattr
*iter
;
693 scan_param
= (gscan_scan_params_t
*)MALLOCZ(cfg
->osh
,
694 sizeof(gscan_scan_params_t
));
696 WL_ERR(("Could not set GSCAN scan cfg, mem alloc failure\n"));
702 scan_param
->scan_fr
= PNO_SCAN_MIN_FW_SEC
;
703 nla_for_each_attr(iter
, data
, len
, tmp
) {
704 type
= nla_type(iter
);
706 if (j
>= GSCAN_MAX_CH_BUCKETS
) {
711 case GSCAN_ATTRIBUTE_BASE_PERIOD
:
712 if (nla_len(iter
) != sizeof(uint32
)) {
716 scan_param
->scan_fr
= nla_get_u32(iter
) / MSEC_PER_SEC
;
718 case GSCAN_ATTRIBUTE_NUM_BUCKETS
:
719 if (nla_len(iter
) != sizeof(uint32
)) {
723 scan_param
->nchannel_buckets
= nla_get_u32(iter
);
724 if (scan_param
->nchannel_buckets
>=
725 GSCAN_MAX_CH_BUCKETS
) {
726 WL_ERR(("ncha_buck out of range %d\n",
727 scan_param
->nchannel_buckets
));
732 case GSCAN_ATTRIBUTE_CH_BUCKET_1
:
733 case GSCAN_ATTRIBUTE_CH_BUCKET_2
:
734 case GSCAN_ATTRIBUTE_CH_BUCKET_3
:
735 case GSCAN_ATTRIBUTE_CH_BUCKET_4
:
736 case GSCAN_ATTRIBUTE_CH_BUCKET_5
:
737 case GSCAN_ATTRIBUTE_CH_BUCKET_6
:
738 case GSCAN_ATTRIBUTE_CH_BUCKET_7
:
739 err
= wl_cfgvendor_set_scan_cfg_bucket(iter
, scan_param
, j
);
741 WL_ERR(("set_scan_cfg_buck error:%d\n", err
));
747 WL_ERR(("Unknown type %d\n", type
));
753 err
= dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg
),
754 DHD_PNO_SCAN_CFG_ID
, scan_param
, FALSE
);
757 WL_ERR(("Could not set GSCAN scan cfg\n"));
762 MFREE(cfg
->osh
, scan_param
, sizeof(gscan_scan_params_t
));
768 wl_cfgvendor_hotlist_cfg(struct wiphy
*wiphy
,
769 struct wireless_dev
*wdev
, const void *data
, int len
)
772 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
773 gscan_hotlist_scan_params_t
*hotlist_params
;
774 int tmp
, tmp1
, tmp2
, type
, j
= 0, dummy
;
775 const struct nlattr
*outer
, *inner
= NULL
, *iter
;
777 struct bssid_t
*pbssid
;
779 BCM_REFERENCE(dummy
);
781 if (len
< sizeof(*hotlist_params
) || len
>= WLC_IOCTL_MAXLEN
) {
782 WL_ERR(("buffer length :%d wrong - bail out.\n", len
));
786 hotlist_params
= (gscan_hotlist_scan_params_t
*)MALLOCZ(cfg
->osh
,
787 sizeof(*hotlist_params
)
788 + (sizeof(struct bssid_t
) * (PFN_SWC_MAX_NUM_APS
- 1)));
790 if (!hotlist_params
) {
791 WL_ERR(("Cannot Malloc memory.\n"));
795 hotlist_params
->lost_ap_window
= GSCAN_LOST_AP_WINDOW_DEFAULT
;
797 nla_for_each_attr(iter
, data
, len
, tmp2
) {
798 type
= nla_type(iter
);
800 case GSCAN_ATTRIBUTE_HOTLIST_BSSID_COUNT
:
801 if (nla_len(iter
) != sizeof(uint32
)) {
802 WL_DBG(("type:%d length:%d not matching.\n",
803 type
, nla_len(iter
)));
807 hotlist_params
->nbssid
= (uint16
)nla_get_u32(iter
);
808 if ((hotlist_params
->nbssid
== 0) ||
809 (hotlist_params
->nbssid
> PFN_SWC_MAX_NUM_APS
)) {
810 WL_ERR(("nbssid:%d exceed limit.\n",
811 hotlist_params
->nbssid
));
816 case GSCAN_ATTRIBUTE_HOTLIST_BSSIDS
:
817 if (hotlist_params
->nbssid
== 0) {
818 WL_ERR(("nbssid not retrieved.\n"));
822 pbssid
= hotlist_params
->bssid
;
823 nla_for_each_nested(outer
, iter
, tmp
) {
824 if (j
>= hotlist_params
->nbssid
)
826 nla_for_each_nested(inner
, outer
, tmp1
) {
827 type
= nla_type(inner
);
830 case GSCAN_ATTRIBUTE_BSSID
:
831 if (nla_len(inner
) != sizeof(pbssid
[j
].macaddr
)) {
832 WL_ERR(("type:%d length:%d not matching.\n",
833 type
, nla_len(inner
)));
838 &(pbssid
[j
].macaddr
),
840 sizeof(pbssid
[j
].macaddr
));
842 case GSCAN_ATTRIBUTE_RSSI_LOW
:
843 if (nla_len(inner
) != sizeof(uint8
)) {
844 WL_ERR(("type:%d length:%d not matching.\n",
845 type
, nla_len(inner
)));
849 pbssid
[j
].rssi_reporting_threshold
=
850 (int8
)nla_get_u8(inner
);
852 case GSCAN_ATTRIBUTE_RSSI_HIGH
:
853 if (nla_len(inner
) != sizeof(uint8
)) {
854 WL_ERR(("type:%d length:%d not matching.\n",
855 type
, nla_len(inner
)));
859 dummy
= (int8
)nla_get_u8(inner
);
860 WL_DBG(("dummy %d\n", dummy
));
863 WL_ERR(("ATTR unknown %d\n", type
));
870 if (j
!= hotlist_params
->nbssid
) {
871 WL_ERR(("bssid_cnt:%d != nbssid:%d.\n", j
,
872 hotlist_params
->nbssid
));
877 case GSCAN_ATTRIBUTE_HOTLIST_FLUSH
:
878 if (nla_len(iter
) != sizeof(uint8
)) {
879 WL_ERR(("type:%d length:%d not matching.\n",
880 type
, nla_len(iter
)));
884 flush
= nla_get_u8(iter
);
886 case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE
:
887 if (nla_len(iter
) != sizeof(uint32
)) {
888 WL_ERR(("type:%d length:%d not matching.\n",
889 type
, nla_len(iter
)));
893 hotlist_params
->lost_ap_window
= (uint16
)nla_get_u32(iter
);
896 WL_ERR(("Unknown type %d\n", type
));
903 if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg
),
904 DHD_PNO_GEOFENCE_SCAN_CFG_ID
, hotlist_params
, flush
) < 0) {
905 WL_ERR(("Could not set GSCAN HOTLIST cfg error: %d\n", err
));
910 MFREE(cfg
->osh
, hotlist_params
, sizeof(*hotlist_params
)
911 + (sizeof(struct bssid_t
) * (PFN_SWC_MAX_NUM_APS
- 1)));
915 static int wl_cfgvendor_epno_cfg(struct wiphy
*wiphy
,
916 struct wireless_dev
*wdev
, const void *data
, int len
)
919 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
920 dhd_pno_ssid_t
*ssid_elem
= NULL
;
921 int tmp
, tmp1
, tmp2
, type
= 0, num
= 0;
922 const struct nlattr
*outer
, *inner
, *iter
;
923 uint8 flush
= FALSE
, i
= 0;
924 wl_ssid_ext_params_t params
;
926 nla_for_each_attr(iter
, data
, len
, tmp2
) {
927 type
= nla_type(iter
);
929 case GSCAN_ATTRIBUTE_EPNO_SSID_LIST
:
930 nla_for_each_nested(outer
, iter
, tmp
) {
931 ssid_elem
= (dhd_pno_ssid_t
*)
932 dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg
),
933 DHD_PNO_GET_NEW_EPNO_SSID_ELEM
,
936 WL_ERR(("Failed to get SSID LIST buffer\n"));
941 nla_for_each_nested(inner
, outer
, tmp1
) {
942 type
= nla_type(inner
);
945 case GSCAN_ATTRIBUTE_EPNO_SSID
:
946 memcpy(ssid_elem
->SSID
,
950 case GSCAN_ATTRIBUTE_EPNO_SSID_LEN
:
951 ssid_elem
->SSID_len
=
953 if (ssid_elem
->SSID_len
>
954 DOT11_MAX_SSID_LEN
) {
957 ssid_elem
->SSID_len
));
959 MFREE(cfg
->osh
, ssid_elem
,
964 case GSCAN_ATTRIBUTE_EPNO_FLAGS
:
969 DHD_EPNO_HIDDEN_SSID
) != 0);
971 case GSCAN_ATTRIBUTE_EPNO_AUTH
:
972 ssid_elem
->wpa_auth
=
977 if (!ssid_elem
->SSID_len
) {
978 WL_ERR(("Broadcast SSID is illegal for ePNO\n"));
980 MFREE(cfg
->osh
, ssid_elem
, num
);
983 dhd_pno_translate_epno_fw_flags(&ssid_elem
->flags
);
984 dhd_pno_set_epno_auth_flag(&ssid_elem
->wpa_auth
);
985 MFREE(cfg
->osh
, ssid_elem
, num
);
988 case GSCAN_ATTRIBUTE_EPNO_SSID_NUM
:
989 num
= nla_get_u8(iter
);
991 case GSCAN_ATTRIBUTE_EPNO_FLUSH
:
992 flush
= (bool)nla_get_u32(iter
);
993 /* Flush attribute is expected before any ssid attribute */
995 WL_ERR(("Bad attributes\n"));
999 /* Need to flush driver and FW cfg */
1000 dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg
),
1001 DHD_PNO_EPNO_CFG_ID
, NULL
, flush
);
1002 dhd_dev_flush_fw_epno(bcmcfg_to_prmry_ndev(cfg
));
1004 case GSCAN_ATTRIBUTE_EPNO_5G_RSSI_THR
:
1005 params
.min5G_rssi
= nla_get_s8(iter
);
1007 case GSCAN_ATTRIBUTE_EPNO_2G_RSSI_THR
:
1008 params
.min2G_rssi
= nla_get_s8(iter
);
1010 case GSCAN_ATTRIBUTE_EPNO_INIT_SCORE_MAX
:
1011 params
.init_score_max
= nla_get_s16(iter
);
1013 case GSCAN_ATTRIBUTE_EPNO_CUR_CONN_BONUS
:
1014 params
.cur_bssid_bonus
= nla_get_s16(iter
);
1016 case GSCAN_ATTRIBUTE_EPNO_SAME_NETWORK_BONUS
:
1017 params
.same_ssid_bonus
= nla_get_s16(iter
);
1019 case GSCAN_ATTRIBUTE_EPNO_SECURE_BONUS
:
1020 params
.secure_bonus
= nla_get_s16(iter
);
1022 case GSCAN_ATTRIBUTE_EPNO_5G_BONUS
:
1023 params
.band_5g_bonus
= nla_get_s16(iter
);
1026 WL_ERR(("%s: No such attribute %d\n", __FUNCTION__
, type
));
1032 WL_ERR(("%s: num_ssid %d does not match ssids sent %d\n", __FUNCTION__
,
1037 /* Flush all configs if error condition */
1039 dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg
),
1040 DHD_PNO_EPNO_CFG_ID
, NULL
, TRUE
);
1041 dhd_dev_flush_fw_epno(bcmcfg_to_prmry_ndev(cfg
));
1042 } else if (type
!= GSCAN_ATTRIBUTE_EPNO_FLUSH
) {
1043 /* If the last attribute was FLUSH, nothing else to do */
1044 dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg
),
1045 DHD_PNO_EPNO_PARAMS_ID
, ¶ms
, FALSE
);
1046 err
= dhd_dev_set_epno(bcmcfg_to_prmry_ndev(cfg
));
1052 wl_cfgvendor_set_batch_scan_cfg(struct wiphy
*wiphy
,
1053 struct wireless_dev
*wdev
, const void *data
, int len
)
1055 int err
= 0, tmp
, type
;
1056 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1057 gscan_batch_params_t batch_param
;
1058 const struct nlattr
*iter
;
1060 batch_param
.mscan
= batch_param
.bestn
= 0;
1061 batch_param
.buffer_threshold
= GSCAN_BATCH_NO_THR_SET
;
1063 nla_for_each_attr(iter
, data
, len
, tmp
) {
1064 type
= nla_type(iter
);
1067 case GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN
:
1068 batch_param
.bestn
= nla_get_u32(iter
);
1070 case GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE
:
1071 batch_param
.mscan
= nla_get_u32(iter
);
1073 case GSCAN_ATTRIBUTE_REPORT_THRESHOLD
:
1074 batch_param
.buffer_threshold
= nla_get_u32(iter
);
1077 WL_ERR(("Unknown type %d\n", type
));
1082 if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg
),
1083 DHD_PNO_BATCH_SCAN_CFG_ID
, &batch_param
, FALSE
) < 0) {
1084 WL_ERR(("Could not set batch cfg\n"));
1092 #endif /* GSCAN_SUPPORT */
1093 #if defined(GSCAN_SUPPORT) || defined(DHD_GET_VALID_CHANNELS)
1095 wl_cfgvendor_gscan_get_channel_list(struct wiphy
*wiphy
,
1096 struct wireless_dev
*wdev
, const void *data
, int len
)
1098 int err
= 0, type
, band
;
1099 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1100 uint16
*reply
= NULL
;
1101 uint32 reply_len
= 0, num_channels
, mem_needed
;
1102 struct sk_buff
*skb
;
1104 type
= nla_type(data
);
1106 if (type
== GSCAN_ATTRIBUTE_BAND
) {
1107 band
= nla_get_u32(data
);
1112 reply
= dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg
),
1113 DHD_PNO_GET_CHANNEL_LIST
, &band
, &reply_len
);
1116 WL_ERR(("Could not get channel list\n"));
1120 num_channels
= reply_len
/ sizeof(uint32
);
1121 mem_needed
= reply_len
+ VENDOR_REPLY_OVERHEAD
+ (ATTRIBUTE_U32_LEN
* 2);
1123 /* Alloc the SKB for vendor_event */
1124 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, mem_needed
);
1125 if (unlikely(!skb
)) {
1126 WL_ERR(("skb alloc failed"));
1131 nla_put_u32(skb
, GSCAN_ATTRIBUTE_NUM_CHANNELS
, num_channels
);
1132 nla_put(skb
, GSCAN_ATTRIBUTE_CHANNEL_LIST
, reply_len
, reply
);
1134 err
= cfg80211_vendor_cmd_reply(skb
);
1136 if (unlikely(err
)) {
1137 WL_ERR(("Vendor Command reply failed ret:%d \n", err
));
1140 MFREE(cfg
->osh
, reply
, reply_len
);
1143 #endif /* GSCAN_SUPPORT || DHD_GET_VALID_CHANNELS */
1145 #ifdef RSSI_MONITOR_SUPPORT
1146 static int wl_cfgvendor_set_rssi_monitor(struct wiphy
*wiphy
,
1147 struct wireless_dev
*wdev
, const void *data
, int len
)
1149 int err
= 0, tmp
, type
, start
= 0;
1150 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1151 int8 max_rssi
= 0, min_rssi
= 0;
1152 const struct nlattr
*iter
;
1154 nla_for_each_attr(iter
, data
, len
, tmp
) {
1155 type
= nla_type(iter
);
1157 case RSSI_MONITOR_ATTRIBUTE_MAX_RSSI
:
1158 max_rssi
= (int8
) nla_get_u32(iter
);
1160 case RSSI_MONITOR_ATTRIBUTE_MIN_RSSI
:
1161 min_rssi
= (int8
) nla_get_u32(iter
);
1163 case RSSI_MONITOR_ATTRIBUTE_START
:
1164 start
= nla_get_u32(iter
);
1168 if (dhd_dev_set_rssi_monitor_cfg(bcmcfg_to_prmry_ndev(cfg
),
1169 start
, max_rssi
, min_rssi
) < 0) {
1170 WL_ERR(("Could not set rssi monitor cfg\n"));
1175 #endif /* RSSI_MONITOR_SUPPORT */
1177 #ifdef DHDTCPACK_SUPPRESS
1179 wl_cfgvendor_set_tcpack_sup_mode(struct wiphy
*wiphy
,
1180 struct wireless_dev
*wdev
, const void *data
, int len
)
1182 int err
= BCME_OK
, type
;
1183 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1184 struct net_device
*ndev
= wdev_to_wlc_ndev(wdev
, cfg
);
1188 WL_ERR(("Length of the nlattr is not valid len : %d\n", len
));
1193 type
= nla_type(data
);
1194 if (type
== ANDR_WIFI_ATTRIBUTE_TCPACK_SUP_VALUE
) {
1195 enable
= (uint8
)nla_get_u32(data
);
1196 err
= dhd_dev_set_tcpack_sup_mode_cfg(ndev
, enable
);
1197 if (unlikely(err
)) {
1198 WL_ERR(("Could not set TCP Ack Suppress mode cfg: %d\n", err
));
1207 #endif /* DHDTCPACK_SUPPRESS */
1209 #ifdef DHD_WAKE_STATUS
1211 wl_cfgvendor_get_wake_reason_stats(struct wiphy
*wiphy
,
1212 struct wireless_dev
*wdev
, const void *data
, int len
)
1214 struct net_device
*ndev
= wdev_to_ndev(wdev
);
1215 wake_counts_t
*pwake_count_info
;
1216 int ret
, mem_needed
;
1217 #if defined(DHD_DEBUG) && defined(DHD_WAKE_EVENT_STATUS)
1219 #endif /* DHD_DEBUG && DHD_WAKE_EVENT_STATUS */
1220 struct sk_buff
*skb
;
1221 dhd_pub_t
*dhdp
= wl_cfg80211_get_dhdp(ndev
);
1223 WL_DBG(("Recv get wake status info cmd.\n"));
1225 pwake_count_info
= dhd_get_wakecount(dhdp
);
1226 mem_needed
= VENDOR_REPLY_OVERHEAD
+ (ATTRIBUTE_U32_LEN
* 20) +
1227 (WLC_E_LAST
* sizeof(uint
));
1229 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, mem_needed
);
1230 if (unlikely(!skb
)) {
1231 WL_ERR(("%s: can't allocate %d bytes\n", __FUNCTION__
, mem_needed
));
1235 #ifdef DHD_WAKE_EVENT_STATUS
1236 WL_ERR(("pwake_count_info->rcwake %d\n", pwake_count_info
->rcwake
));
1237 nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT
, pwake_count_info
->rcwake
);
1238 nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_CMD_EVENT_COUNT_USED
, WLC_E_LAST
);
1239 nla_put(skb
, WAKE_STAT_ATTRIBUTE_CMD_EVENT_WAKE
, (WLC_E_LAST
* sizeof(uint
)),
1240 pwake_count_info
->rc_event
);
1242 for (flowid
= 0; flowid
< WLC_E_LAST
; flowid
++) {
1243 if (pwake_count_info
->rc_event
[flowid
] != 0) {
1244 WL_ERR((" %s = %u\n", bcmevent_get_name(flowid
),
1245 pwake_count_info
->rc_event
[flowid
]));
1248 #endif /* DHD_DEBUG */
1249 #endif /* DHD_WAKE_EVENT_STATUS */
1250 #ifdef DHD_WAKE_RX_STATUS
1251 WL_ERR(("pwake_count_info->rxwake %d\n", pwake_count_info
->rxwake
));
1252 nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_TOTAL_RX_DATA_WAKE
, pwake_count_info
->rxwake
);
1253 nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_RX_UNICAST_COUNT
, pwake_count_info
->rx_ucast
);
1254 nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_RX_MULTICAST_COUNT
, pwake_count_info
->rx_mcast
);
1255 nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_RX_BROADCAST_COUNT
, pwake_count_info
->rx_bcast
);
1256 nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_RX_ICMP_PKT
, pwake_count_info
->rx_arp
);
1257 nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_RX_ICMP6_PKT
, pwake_count_info
->rx_icmpv6
);
1258 nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_RX_ICMP6_RA
, pwake_count_info
->rx_icmpv6_ra
);
1259 nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_RX_ICMP6_NA
, pwake_count_info
->rx_icmpv6_na
);
1260 nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_RX_ICMP6_NS
, pwake_count_info
->rx_icmpv6_ns
);
1261 nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_IPV4_RX_MULTICAST_ADD_CNT
,
1262 pwake_count_info
->rx_multi_ipv4
);
1263 nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_IPV6_RX_MULTICAST_ADD_CNT
,
1264 pwake_count_info
->rx_multi_ipv6
);
1265 nla_put_u32(skb
, WAKE_STAT_ATTRIBUTE_OTHER_RX_MULTICAST_ADD_CNT
,
1266 pwake_count_info
->rx_multi_other
);
1267 #endif /* #ifdef DHD_WAKE_RX_STATUS */
1268 ret
= cfg80211_vendor_cmd_reply(skb
);
1269 if (unlikely(ret
)) {
1270 WL_ERR(("Vendor cmd reply for -get wake status failed:%d \n", ret
));
1275 #endif /* DHD_WAKE_STATUS */
1279 wl_cfgvendor_rtt_evt(void *ctx
, void *rtt_data
)
1281 struct wireless_dev
*wdev
= (struct wireless_dev
*)ctx
;
1282 struct wiphy
*wiphy
;
1283 struct sk_buff
*skb
;
1284 uint32 evt_complete
= 0;
1286 rtt_result_t
*rtt_result
;
1287 rtt_results_header_t
*rtt_header
;
1288 struct list_head
*rtt_cache_list
;
1289 struct nlattr
*rtt_nl_hdr
;
1290 wiphy
= wdev
->wiphy
;
1293 /* Push the data to the skb */
1295 WL_ERR(("rtt_data is NULL\n"));
1298 rtt_cache_list
= (struct list_head
*)rtt_data
;
1299 kflags
= in_atomic() ? GFP_ATOMIC
: GFP_KERNEL
;
1300 if (list_empty(rtt_cache_list
)) {
1301 #if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
1302 LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
1303 skb
= cfg80211_vendor_event_alloc(wiphy
, NULL
, 100,
1304 GOOGLE_RTT_COMPLETE_EVENT
, kflags
);
1306 skb
= cfg80211_vendor_event_alloc(wiphy
, 100, GOOGLE_RTT_COMPLETE_EVENT
, kflags
);
1307 #endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
1308 /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */
1310 WL_ERR(("skb alloc failed"));
1314 nla_put_u32(skb
, RTT_ATTRIBUTE_RESULTS_COMPLETE
, evt_complete
);
1315 cfg80211_vendor_event(skb
, kflags
);
1318 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
1319 #pragma GCC diagnostic push
1320 #pragma GCC diagnostic ignored "-Wcast-qual"
1322 list_for_each_entry(rtt_header
, rtt_cache_list
, list
) {
1323 /* Alloc the SKB for vendor_event */
1324 #if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
1325 LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
1326 skb
= cfg80211_vendor_event_alloc(wiphy
, NULL
, rtt_header
->result_tot_len
+ 100,
1327 GOOGLE_RTT_COMPLETE_EVENT
, kflags
);
1329 skb
= cfg80211_vendor_event_alloc(wiphy
, rtt_header
->result_tot_len
+ 100,
1330 GOOGLE_RTT_COMPLETE_EVENT
, kflags
);
1331 #endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
1332 /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */
1334 WL_ERR(("skb alloc failed"));
1337 if (list_is_last(&rtt_header
->list
, rtt_cache_list
)) {
1340 nla_put_u32(skb
, RTT_ATTRIBUTE_RESULTS_COMPLETE
, evt_complete
);
1341 rtt_nl_hdr
= nla_nest_start(skb
, RTT_ATTRIBUTE_RESULTS_PER_TARGET
);
1343 WL_ERR(("rtt_nl_hdr is NULL\n"));
1346 nla_put(skb
, RTT_ATTRIBUTE_TARGET_MAC
, ETHER_ADDR_LEN
, &rtt_header
->peer_mac
);
1347 nla_put_u32(skb
, RTT_ATTRIBUTE_RESULT_CNT
, rtt_header
->result_cnt
);
1348 list_for_each_entry(rtt_result
, &rtt_header
->result_list
, list
) {
1349 nla_put(skb
, RTT_ATTRIBUTE_RESULT
,
1350 rtt_result
->report_len
, &rtt_result
->report
);
1352 nla_nest_end(skb
, rtt_nl_hdr
);
1353 cfg80211_vendor_event(skb
, kflags
);
1355 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
1356 #pragma GCC diagnostic pop
1361 wl_cfgvendor_rtt_set_config(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
1362 const void *data
, int len
) {
1363 int err
= 0, rem
, rem1
, rem2
, type
;
1365 rtt_config_params_t rtt_param
;
1366 rtt_target_info_t
* rtt_target
= NULL
;
1367 const struct nlattr
*iter
, *iter1
, *iter2
;
1368 int8 eabuf
[ETHER_ADDR_STR_LEN
];
1369 int8 chanbuf
[CHANSPEC_STR_LEN
];
1370 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1371 rtt_capabilities_t capability
;
1373 memset(&rtt_param
, 0, sizeof(rtt_param
));
1376 err
= dhd_dev_rtt_register_noti_callback(wdev
->netdev
, wdev
, wl_cfgvendor_rtt_evt
);
1378 WL_ERR(("failed to register rtt_noti_callback\n"));
1381 err
= dhd_dev_rtt_capability(bcmcfg_to_prmry_ndev(cfg
), &capability
);
1383 WL_ERR(("failed to get the capability\n"));
1388 WL_ERR(("Length of the nlattr is not valid len : %d\n", len
));
1392 nla_for_each_attr(iter
, data
, len
, rem
) {
1393 type
= nla_type(iter
);
1395 case RTT_ATTRIBUTE_TARGET_CNT
:
1396 target_cnt
= nla_get_u8(iter
);
1397 if ((target_cnt
<= 0) || (target_cnt
> RTT_MAX_TARGET_CNT
)) {
1398 WL_ERR(("target_cnt is not valid : %d\n",
1403 rtt_param
.rtt_target_cnt
= target_cnt
;
1405 rtt_param
.target_info
= (rtt_target_info_t
*)MALLOCZ(cfg
->osh
,
1406 TARGET_INFO_SIZE(target_cnt
));
1407 if (rtt_param
.target_info
== NULL
) {
1408 WL_ERR(("failed to allocate target info for (%d)\n", target_cnt
));
1413 case RTT_ATTRIBUTE_TARGET_INFO
:
1414 /* Added this variable for safe check to avoid crash
1415 * incase the caller did not respect the order
1417 if (rtt_param
.target_info
== NULL
) {
1418 WL_ERR(("rtt_target_info is NULL\n"));
1422 rtt_target
= rtt_param
.target_info
;
1423 nla_for_each_nested(iter1
, iter
, rem1
) {
1424 nla_for_each_nested(iter2
, iter1
, rem2
) {
1425 type
= nla_type(iter2
);
1427 case RTT_ATTRIBUTE_TARGET_MAC
:
1428 memcpy(&rtt_target
->addr
, nla_data(iter2
),
1431 case RTT_ATTRIBUTE_TARGET_TYPE
:
1432 rtt_target
->type
= nla_get_u8(iter2
);
1433 if (rtt_target
->type
== RTT_INVALID
||
1434 (rtt_target
->type
== RTT_ONE_WAY
&&
1435 !capability
.rtt_one_sided_supported
)) {
1436 WL_ERR(("doesn't support RTT type"
1443 case RTT_ATTRIBUTE_TARGET_PEER
:
1444 rtt_target
->peer
= nla_get_u8(iter2
);
1446 case RTT_ATTRIBUTE_TARGET_CHAN
:
1447 memcpy(&rtt_target
->channel
, nla_data(iter2
),
1448 sizeof(rtt_target
->channel
));
1450 case RTT_ATTRIBUTE_TARGET_PERIOD
:
1451 rtt_target
->burst_period
= nla_get_u32(iter2
);
1452 if (rtt_target
->burst_period
< 32) {
1454 rtt_target
->burst_period
*= 100;
1456 WL_ERR(("%d value must in (0-31)\n",
1457 rtt_target
->burst_period
));
1462 case RTT_ATTRIBUTE_TARGET_NUM_BURST
:
1463 rtt_target
->num_burst
= nla_get_u32(iter2
);
1464 if (rtt_target
->num_burst
> 16) {
1465 WL_ERR(("%d value must in (0-15)\n",
1466 rtt_target
->num_burst
));
1470 rtt_target
->num_burst
= BIT(rtt_target
->num_burst
);
1472 case RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST
:
1473 rtt_target
->num_frames_per_burst
=
1476 case RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM
:
1477 rtt_target
->num_retries_per_ftm
=
1480 case RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR
:
1481 rtt_target
->num_retries_per_ftmr
=
1483 if (rtt_target
->num_retries_per_ftmr
> 3) {
1484 WL_ERR(("%d value must in (0-3)\n",
1485 rtt_target
->num_retries_per_ftmr
));
1490 case RTT_ATTRIBUTE_TARGET_LCI
:
1491 rtt_target
->LCI_request
= nla_get_u8(iter2
);
1493 case RTT_ATTRIBUTE_TARGET_LCR
:
1494 rtt_target
->LCI_request
= nla_get_u8(iter2
);
1496 case RTT_ATTRIBUTE_TARGET_BURST_DURATION
:
1497 if ((nla_get_u32(iter2
) > 1 &&
1498 nla_get_u32(iter2
) < 12)) {
1499 rtt_target
->burst_duration
=
1500 dhd_rtt_idx_to_burst_duration(
1501 nla_get_u32(iter2
));
1502 } else if (nla_get_u32(iter2
) == 15) {
1503 /* use default value */
1504 rtt_target
->burst_duration
= 0;
1506 WL_ERR(("%d value must in (2-11) or 15\n",
1507 nla_get_u32(iter2
)));
1512 case RTT_ATTRIBUTE_TARGET_BW
:
1513 rtt_target
->bw
= nla_get_u8(iter2
);
1515 case RTT_ATTRIBUTE_TARGET_PREAMBLE
:
1516 rtt_target
->preamble
= nla_get_u8(iter2
);
1520 /* convert to chanspec value */
1521 rtt_target
->chanspec
=
1522 dhd_rtt_convert_to_chspec(rtt_target
->channel
);
1523 if (rtt_target
->chanspec
== 0) {
1524 WL_ERR(("Channel is not valid \n"));
1528 WL_INFORM_MEM(("Target addr %s, Channel : %s for RTT \n",
1529 bcm_ether_ntoa((const struct ether_addr
*)&rtt_target
->addr
,
1531 wf_chspec_ntoa(rtt_target
->chanspec
, chanbuf
)));
1537 WL_DBG(("leave :target_cnt : %d\n", rtt_param
.rtt_target_cnt
));
1538 if (dhd_dev_rtt_set_cfg(bcmcfg_to_prmry_ndev(cfg
), &rtt_param
) < 0) {
1539 WL_ERR(("Could not set RTT configuration\n"));
1543 /* free the target info list */
1544 if (rtt_param
.target_info
) {
1545 MFREE(cfg
->osh
, rtt_param
.target_info
,
1546 TARGET_INFO_SIZE(target_cnt
));
1547 rtt_param
.target_info
= NULL
;
1553 wl_cfgvendor_rtt_cancel_config(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
1554 const void *data
, int len
)
1556 int err
= 0, rem
, type
, target_cnt
= 0;
1558 const struct nlattr
*iter
;
1559 struct ether_addr
*mac_list
= NULL
;
1560 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1563 WL_ERR(("Length of nlattr is not valid len : %d\n", len
));
1567 nla_for_each_attr(iter
, data
, len
, rem
) {
1568 type
= nla_type(iter
);
1570 case RTT_ATTRIBUTE_TARGET_CNT
:
1571 if (mac_list
!= NULL
) {
1572 WL_ERR(("mac_list is not NULL\n"));
1576 target_cnt
= nla_get_u8(iter
);
1577 if ((target_cnt
> 0) && (target_cnt
< RTT_MAX_TARGET_CNT
)) {
1578 mac_list
= (struct ether_addr
*)MALLOCZ(cfg
->osh
,
1579 target_cnt
* ETHER_ADDR_LEN
);
1580 if (mac_list
== NULL
) {
1581 WL_ERR(("failed to allocate mem for mac list\n"));
1586 /* cancel the current whole RTT process */
1590 case RTT_ATTRIBUTE_TARGET_MAC
:
1591 if (mac_list
== NULL
) {
1592 WL_ERR(("ATTRIBUTE_TARGET_CNT not found before "
1593 " ATTRIBUTE_TARGET_MAC\n"));
1598 if (target_idx
>= target_cnt
) {
1599 WL_ERR(("More TARGET_MAC entries found, "
1600 "expected TARGET_CNT:%d\n", target_cnt
));
1605 if (nla_len(iter
) != ETHER_ADDR_LEN
) {
1606 WL_ERR(("Invalid TARGET_MAC ATTR len :%d\n", nla_len(iter
)));
1611 memcpy(&mac_list
[target_idx
], nla_data(iter
), ETHER_ADDR_LEN
);
1616 WL_ERR(("Uknown type : %d\n", type
));
1622 if (dhd_dev_rtt_cancel_cfg(bcmcfg_to_prmry_ndev(cfg
), mac_list
, target_cnt
) < 0) {
1623 WL_ERR(("Could not cancel RTT configuration\n"));
1629 MFREE(cfg
->osh
, mac_list
, target_cnt
* ETHER_ADDR_LEN
);
1635 wl_cfgvendor_rtt_get_capability(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
1636 const void *data
, int len
)
1639 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1640 rtt_capabilities_t capability
;
1642 err
= dhd_dev_rtt_capability(bcmcfg_to_prmry_ndev(cfg
), &capability
);
1643 if (unlikely(err
)) {
1644 WL_ERR(("Vendor Command reply failed ret:%d \n", err
));
1647 err
= wl_cfgvendor_send_cmd_reply(wiphy
, &capability
, sizeof(capability
));
1649 if (unlikely(err
)) {
1650 WL_ERR(("Vendor Command reply failed ret:%d \n", err
));
1656 get_responder_info(struct bcm_cfg80211
*cfg
,
1657 struct wifi_rtt_responder
*responder_info
)
1660 rtt_capabilities_t capability
;
1661 err
= dhd_dev_rtt_capability(bcmcfg_to_prmry_ndev(cfg
), &capability
);
1662 if (unlikely(err
)) {
1663 WL_ERR(("Could not get responder capability:%d \n", err
));
1666 if (capability
.preamble_support
& RTT_PREAMBLE_VHT
) {
1667 responder_info
->preamble
|= RTT_PREAMBLE_VHT
;
1669 if (capability
.preamble_support
& RTT_PREAMBLE_HT
) {
1670 responder_info
->preamble
|= RTT_PREAMBLE_HT
;
1672 err
= dhd_dev_rtt_avail_channel(bcmcfg_to_prmry_ndev(cfg
), &(responder_info
->channel
));
1673 if (unlikely(err
)) {
1674 WL_ERR(("Could not get available channel:%d \n", err
));
1680 wl_cfgvendor_rtt_get_responder_info(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
1681 const void *data
, int len
)
1684 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1685 wifi_rtt_responder_t responder_info
;
1687 WL_DBG(("Recv -get_avail_ch command \n"));
1689 memset(&responder_info
, 0, sizeof(responder_info
));
1690 err
= get_responder_info(cfg
, &responder_info
);
1691 if (unlikely(err
)) {
1692 WL_ERR(("Failed to get responder info:%d \n", err
));
1695 err
= wl_cfgvendor_send_cmd_reply(wiphy
, &responder_info
, sizeof(responder_info
));
1696 if (unlikely(err
)) {
1697 WL_ERR(("Vendor cmd reply for -get_avail_ch failed ret:%d \n", err
));
1703 wl_cfgvendor_rtt_set_responder(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
1704 const void *data
, int len
)
1707 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1708 struct net_device
*ndev
= wdev_to_wlc_ndev(wdev
, cfg
);
1709 wifi_rtt_responder_t responder_info
;
1711 WL_DBG(("Recv rtt -enable_resp cmd.\n"));
1713 memset(&responder_info
, 0, sizeof(responder_info
));
1716 *Passing channel as NULL until implementation
1717 *to get chan info from upper layers is donex
1719 err
= dhd_dev_rtt_enable_responder(ndev
, NULL
);
1720 if (unlikely(err
)) {
1721 WL_ERR(("Could not enable responder ret:%d \n", err
));
1724 err
= get_responder_info(cfg
, &responder_info
);
1725 if (unlikely(err
)) {
1726 WL_ERR(("Failed to get responder info:%d \n", err
));
1727 dhd_dev_rtt_cancel_responder(ndev
);
1731 err
= wl_cfgvendor_send_cmd_reply(wiphy
, &responder_info
, sizeof(responder_info
));
1732 if (unlikely(err
)) {
1733 WL_ERR(("Vendor cmd reply for -enable_resp failed ret:%d \n", err
));
1739 wl_cfgvendor_rtt_cancel_responder(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
1740 const void *data
, int len
)
1743 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1745 WL_DBG(("Recv rtt -cancel_resp cmd \n"));
1747 err
= dhd_dev_rtt_cancel_responder(bcmcfg_to_prmry_ndev(cfg
));
1748 if (unlikely(err
)) {
1749 WL_ERR(("Vendor cmd -cancel_resp failed ret:%d \n", err
));
1753 #endif /* RTT_SUPPORT */
1755 #ifdef GSCAN_SUPPORT
1756 static int wl_cfgvendor_enable_lazy_roam(struct wiphy
*wiphy
,
1757 struct wireless_dev
*wdev
, const void *data
, int len
)
1760 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1762 uint32 lazy_roam_enable_flag
;
1764 type
= nla_type(data
);
1766 if (type
== GSCAN_ATTRIBUTE_LAZY_ROAM_ENABLE
) {
1767 lazy_roam_enable_flag
= nla_get_u32(data
);
1769 err
= dhd_dev_lazy_roam_enable(bcmcfg_to_prmry_ndev(cfg
),
1770 lazy_roam_enable_flag
);
1772 WL_ERR(("Could not enable lazy roam:%d \n", err
));
1777 static int wl_cfgvendor_set_lazy_roam_cfg(struct wiphy
*wiphy
,
1778 struct wireless_dev
*wdev
, const void *data
, int len
)
1780 int err
= 0, tmp
, type
;
1781 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1782 wlc_roam_exp_params_t roam_param
;
1783 const struct nlattr
*iter
;
1785 memset(&roam_param
, 0, sizeof(roam_param
));
1787 nla_for_each_attr(iter
, data
, len
, tmp
) {
1788 type
= nla_type(iter
);
1790 case GSCAN_ATTRIBUTE_A_BAND_BOOST_THRESHOLD
:
1791 roam_param
.a_band_boost_threshold
= nla_get_u32(iter
);
1793 case GSCAN_ATTRIBUTE_A_BAND_PENALTY_THRESHOLD
:
1794 roam_param
.a_band_penalty_threshold
= nla_get_u32(iter
);
1796 case GSCAN_ATTRIBUTE_A_BAND_BOOST_FACTOR
:
1797 roam_param
.a_band_boost_factor
= nla_get_u32(iter
);
1799 case GSCAN_ATTRIBUTE_A_BAND_PENALTY_FACTOR
:
1800 roam_param
.a_band_penalty_factor
= nla_get_u32(iter
);
1802 case GSCAN_ATTRIBUTE_A_BAND_MAX_BOOST
:
1803 roam_param
.a_band_max_boost
= nla_get_u32(iter
);
1805 case GSCAN_ATTRIBUTE_LAZY_ROAM_HYSTERESIS
:
1806 roam_param
.cur_bssid_boost
= nla_get_u32(iter
);
1808 case GSCAN_ATTRIBUTE_ALERT_ROAM_RSSI_TRIGGER
:
1809 roam_param
.alert_roam_trigger_threshold
= nla_get_u32(iter
);
1814 if (dhd_dev_set_lazy_roam_cfg(bcmcfg_to_prmry_ndev(cfg
), &roam_param
) < 0) {
1815 WL_ERR(("Could not set batch cfg\n"));
1821 /* small helper function */
1822 static wl_bssid_pref_cfg_t
*
1823 create_bssid_pref_cfg(struct bcm_cfg80211
*cfg
, uint32 num
, uint32
*buf_len
)
1825 wl_bssid_pref_cfg_t
*bssid_pref
;
1827 *buf_len
= sizeof(wl_bssid_pref_cfg_t
);
1829 *buf_len
+= (num
- 1) * sizeof(wl_bssid_pref_list_t
);
1831 bssid_pref
= (wl_bssid_pref_cfg_t
*)MALLOC(cfg
->osh
, *buf_len
);
1837 wl_cfgvendor_set_bssid_pref(struct wiphy
*wiphy
,
1838 struct wireless_dev
*wdev
, const void *data
, int len
)
1841 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1842 wl_bssid_pref_cfg_t
*bssid_pref
= NULL
;
1843 wl_bssid_pref_list_t
*bssids
;
1844 int tmp
, tmp1
, tmp2
, type
;
1845 const struct nlattr
*outer
, *inner
, *iter
;
1846 uint32 flush
= 0, num
= 0, buf_len
= 0;
1847 uint8 bssid_found
= 0, rssi_found
= 0;
1849 /* Assumption: NUM attribute must come first */
1850 nla_for_each_attr(iter
, data
, len
, tmp2
) {
1851 type
= nla_type(iter
);
1853 case GSCAN_ATTRIBUTE_NUM_BSSID
:
1855 WL_ERR(("attempt overide bssid num.\n"));
1859 if (nla_len(iter
) != sizeof(uint32
)) {
1860 WL_ERR(("nla_len not match\n"));
1864 num
= nla_get_u32(iter
);
1865 if (num
== 0 || num
> MAX_BSSID_PREF_LIST_NUM
) {
1866 WL_ERR(("wrong BSSID num:%d\n", num
));
1870 if ((bssid_pref
= create_bssid_pref_cfg(cfg
, num
, &buf_len
))
1872 WL_ERR(("Can't malloc memory\n"));
1877 case GSCAN_ATTRIBUTE_BSSID_PREF_FLUSH
:
1878 if (nla_len(iter
) != sizeof(uint32
)) {
1879 WL_ERR(("nla_len not match\n"));
1883 flush
= nla_get_u32(iter
);
1885 WL_ERR(("wrong flush value\n"));
1890 case GSCAN_ATTRIBUTE_BSSID_PREF_LIST
:
1891 if (!num
|| !bssid_pref
) {
1892 WL_ERR(("bssid list count not set\n"));
1896 bssid_pref
->count
= 0;
1897 bssids
= bssid_pref
->bssids
;
1898 nla_for_each_nested(outer
, iter
, tmp
) {
1899 if (bssid_pref
->count
>= num
) {
1900 WL_ERR(("too many bssid list\n"));
1906 nla_for_each_nested(inner
, outer
, tmp1
) {
1907 type
= nla_type(inner
);
1909 case GSCAN_ATTRIBUTE_BSSID_PREF
:
1910 if (nla_len(inner
) != ETHER_ADDR_LEN
) {
1911 WL_ERR(("nla_len not match.\n"));
1915 memcpy(&(bssids
[bssid_pref
->count
].bssid
),
1916 nla_data(inner
), ETHER_ADDR_LEN
);
1917 /* not used for now */
1918 bssids
[bssid_pref
->count
].flags
= 0;
1921 case GSCAN_ATTRIBUTE_RSSI_MODIFIER
:
1922 if (nla_len(inner
) != sizeof(uint32
)) {
1923 WL_ERR(("nla_len not match.\n"));
1927 bssids
[bssid_pref
->count
].rssi_factor
=
1928 (int8
) nla_get_u32(inner
);
1932 WL_ERR(("wrong type:%d\n", type
));
1936 if (bssid_found
&& rssi_found
) {
1940 bssid_pref
->count
++;
1944 WL_ERR(("%s: No such attribute %d\n", __FUNCTION__
, type
));
1950 /* What if only flush is desired? */
1952 if ((bssid_pref
= create_bssid_pref_cfg(cfg
, 0, &buf_len
)) == NULL
) {
1953 WL_ERR(("%s: Can't malloc memory\n", __FUNCTION__
));
1957 bssid_pref
->count
= 0;
1963 err
= dhd_dev_set_lazy_roam_bssid_pref(bcmcfg_to_prmry_ndev(cfg
),
1967 MFREE(cfg
->osh
, bssid_pref
, buf_len
);
1971 #endif /* GSCAN_SUPPORT */
1972 #if defined(GSCAN_SUPPORT) || defined(ROAMEXP_SUPPORT)
1974 wl_cfgvendor_set_bssid_blacklist(struct wiphy
*wiphy
,
1975 struct wireless_dev
*wdev
, const void *data
, int len
)
1977 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1978 maclist_t
*blacklist
= NULL
;
1981 const struct nlattr
*iter
;
1982 uint32 mem_needed
= 0, flush
= 0, num
= 0;
1984 /* Assumption: NUM attribute must come first */
1985 nla_for_each_attr(iter
, data
, len
, tmp
) {
1986 type
= nla_type(iter
);
1988 case GSCAN_ATTRIBUTE_NUM_BSSID
:
1990 WL_ERR(("attempt to change BSSID num\n"));
1994 if (nla_len(iter
) != sizeof(uint32
)) {
1995 WL_ERR(("not matching nla_len.\n"));
1999 num
= nla_get_u32(iter
);
2000 if (num
== 0 || num
> MAX_BSSID_BLACKLIST_NUM
) {
2001 WL_ERR(("wrong BSSID count:%d\n", num
));
2006 mem_needed
= OFFSETOF(maclist_t
, ea
) +
2007 sizeof(struct ether_addr
) * (num
);
2008 blacklist
= (maclist_t
*)
2009 MALLOCZ(cfg
->osh
, mem_needed
);
2011 WL_ERR(("MALLOCZ failed.\n"));
2017 case GSCAN_ATTRIBUTE_BSSID_BLACKLIST_FLUSH
:
2018 if (nla_len(iter
) != sizeof(uint32
)) {
2019 WL_ERR(("not matching nla_len.\n"));
2023 flush
= nla_get_u32(iter
);
2025 WL_ERR(("flush arg is worng:%d\n", flush
));
2030 case GSCAN_ATTRIBUTE_BLACKLIST_BSSID
:
2031 if (num
== 0 || !blacklist
) {
2032 WL_ERR(("number of BSSIDs not received.\n"));
2036 if (nla_len(iter
) != ETHER_ADDR_LEN
) {
2037 WL_ERR(("not matching nla_len.\n"));
2041 if (blacklist
->count
>= num
) {
2042 WL_ERR(("too many BSSIDs than expected:%d\n",
2047 memcpy(&(blacklist
->ea
[blacklist
->count
]), nla_data(iter
),
2052 WL_ERR(("No such attribute:%d\n", type
));
2057 if (blacklist
&& (blacklist
->count
!= num
)) {
2058 WL_ERR(("not matching bssid count:%d to expected:%d\n",
2059 blacklist
->count
, num
));
2064 err
= dhd_dev_set_blacklist_bssid(bcmcfg_to_prmry_ndev(cfg
),
2065 blacklist
, mem_needed
, flush
);
2067 MFREE(cfg
->osh
, blacklist
, mem_needed
);
2072 wl_cfgvendor_set_ssid_whitelist(struct wiphy
*wiphy
,
2073 struct wireless_dev
*wdev
, const void *data
, int len
)
2076 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
2077 wl_ssid_whitelist_t
*ssid_whitelist
= NULL
;
2078 wlc_ssid_t
*ssid_elem
;
2079 int tmp
, tmp1
, mem_needed
= 0, type
;
2080 const struct nlattr
*iter
, *iter1
;
2081 uint32 flush
= 0, num
= 0;
2084 /* Assumption: NUM attribute must come first */
2085 nla_for_each_attr(iter
, data
, len
, tmp
) {
2086 type
= nla_type(iter
);
2088 case GSCAN_ATTRIBUTE_NUM_WL_SSID
:
2090 WL_ERR(("try to change SSID num\n"));
2094 if (nla_len(iter
) != sizeof(uint32
)) {
2095 WL_ERR(("not matching nla_len.\n"));
2099 num
= nla_get_u32(iter
);
2100 if (num
== 0 || num
> MAX_SSID_WHITELIST_NUM
) {
2101 WL_ERR(("wrong SSID count:%d\n", num
));
2105 mem_needed
= sizeof(wl_ssid_whitelist_t
) +
2106 sizeof(wlc_ssid_t
) * num
;
2107 ssid_whitelist
= (wl_ssid_whitelist_t
*)
2108 MALLOCZ(cfg
->osh
, mem_needed
);
2109 if (ssid_whitelist
== NULL
) {
2110 WL_ERR(("failed to alloc mem\n"));
2115 case GSCAN_ATTRIBUTE_WL_SSID_FLUSH
:
2116 if (nla_len(iter
) != sizeof(uint32
)) {
2117 WL_ERR(("not matching nla_len.\n"));
2121 flush
= nla_get_u32(iter
);
2123 WL_ERR(("flush arg worng:%d\n", flush
));
2128 case GSCAN_ATTRIBUTE_WHITELIST_SSID_ELEM
:
2129 if (!num
|| !ssid_whitelist
) {
2130 WL_ERR(("num ssid is not set!\n"));
2134 if (ssid_whitelist
->ssid_count
>= num
) {
2135 WL_ERR(("too many SSIDs:%d\n",
2136 ssid_whitelist
->ssid_count
));
2141 ssid_elem
= &ssid_whitelist
->ssids
[
2142 ssid_whitelist
->ssid_count
];
2144 nla_for_each_nested(iter1
, iter
, tmp1
) {
2145 type
= nla_type(iter1
);
2147 case GSCAN_ATTRIBUTE_WL_SSID_LEN
:
2148 if (nla_len(iter1
) != sizeof(uint32
)) {
2149 WL_ERR(("not match nla_len\n"));
2153 ssid_elem
->SSID_len
= nla_get_u32(iter1
);
2154 if (ssid_elem
->SSID_len
>
2155 DOT11_MAX_SSID_LEN
) {
2156 WL_ERR(("wrong SSID len:%d\n",
2157 ssid_elem
->SSID_len
));
2162 case GSCAN_ATTRIBUTE_WHITELIST_SSID
:
2163 if (ssid_elem
->SSID_len
== 0) {
2164 WL_ERR(("SSID_len not received\n"));
2168 if (nla_len(iter1
) != ssid_elem
->SSID_len
) {
2169 WL_ERR(("not match nla_len\n"));
2173 memcpy(ssid_elem
->SSID
, nla_data(iter1
),
2174 ssid_elem
->SSID_len
);
2179 ssid_whitelist
->ssid_count
++;
2185 WL_ERR(("No such attribute: %d\n", type
));
2190 if (ssid_whitelist
&& (ssid_whitelist
->ssid_count
!= num
)) {
2191 WL_ERR(("not matching ssid count:%d to expected:%d\n",
2192 ssid_whitelist
->ssid_count
, num
));
2195 err
= dhd_dev_set_whitelist_ssid(bcmcfg_to_prmry_ndev(cfg
),
2196 ssid_whitelist
, mem_needed
, flush
);
2198 MFREE(cfg
->osh
, ssid_whitelist
, mem_needed
);
2201 #endif /* GSCAN_SUPPORT || ROAMEXP_SUPPORT */
2203 #ifdef ROAMEXP_SUPPORT
2205 FW_ROAMING_ENABLE
= 1,
2209 } fw_roaming_state_t
;
2212 wl_cfgvendor_set_fw_roaming_state(struct wiphy
*wiphy
,
2213 struct wireless_dev
*wdev
, const void *data
, int len
)
2215 fw_roaming_state_t requested_roaming_state
;
2219 /* Get the requested fw roaming state */
2220 type
= nla_type(data
);
2221 if (type
!= GSCAN_ATTRIBUTE_ROAM_STATE_SET
) {
2222 WL_ERR(("%s: Invalid attribute %d\n", __FUNCTION__
, type
));
2226 requested_roaming_state
= nla_get_u32(data
);
2227 WL_INFORM(("setting FW roaming state to %d\n", requested_roaming_state
));
2229 if ((requested_roaming_state
== FW_ROAMING_ENABLE
) ||
2230 (requested_roaming_state
== FW_ROAMING_RESUME
)) {
2231 err
= wldev_iovar_setint(wdev_to_ndev(wdev
), "roam_off", FALSE
);
2232 } else if ((requested_roaming_state
== FW_ROAMING_DISABLE
) ||
2233 (requested_roaming_state
== FW_ROAMING_PAUSE
)) {
2234 err
= wldev_iovar_setint(wdev_to_ndev(wdev
), "roam_off", TRUE
);
2243 wl_cfgvendor_fw_roam_get_capability(struct wiphy
*wiphy
,
2244 struct wireless_dev
*wdev
, const void *data
, int len
)
2247 wifi_roaming_capabilities_t roaming_capability
;
2249 /* Update max number of blacklist bssids supported */
2250 roaming_capability
.max_blacklist_size
= MAX_BSSID_BLACKLIST_NUM
;
2251 roaming_capability
.max_whitelist_size
= MAX_SSID_WHITELIST_NUM
;
2252 err
= wl_cfgvendor_send_cmd_reply(wiphy
, &roaming_capability
,
2253 sizeof(roaming_capability
));
2254 if (unlikely(err
)) {
2255 WL_ERR(("Vendor cmd reply for fw roam capability failed ret:%d \n", err
));
2260 #endif /* ROAMEXP_SUPPORT */
2263 wl_cfgvendor_priv_string_handler(struct wiphy
*wiphy
,
2264 struct wireless_dev
*wdev
, const void *data
, int len
)
2266 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
2268 int ret_len
= 0, payload
= 0, msglen
;
2269 const struct bcm_nlmsg_hdr
*nlioc
= data
;
2270 void *buf
= NULL
, *cur
;
2271 int maxmsglen
= PAGE_SIZE
- 0x100;
2272 struct sk_buff
*reply
;
2273 dhd_pub_t
*dhdp
= wl_cfg80211_get_dhdp(wdev
->netdev
);
2275 WL_DBG(("entry: cmd = %d\n", nlioc
->cmd
));
2277 /* send to dongle only if we are not waiting for reload already */
2278 if (dhdp
&& dhdp
->hang_was_sent
) {
2279 WL_INFORM(("Bus down. HANG was sent up earlier\n"));
2280 DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhdp
, DHD_EVENT_TIMEOUT_MS
);
2281 DHD_OS_WAKE_UNLOCK(dhdp
);
2282 return OSL_ERROR(BCME_DONGLE_DOWN
);
2285 if (nlioc
->offset
!= sizeof(struct bcm_nlmsg_hdr
) ||
2286 len
<= sizeof(struct bcm_nlmsg_hdr
)) {
2287 WL_ERR(("invalid offset %d\n", nlioc
->offset
));
2290 len
-= sizeof(struct bcm_nlmsg_hdr
);
2291 ret_len
= nlioc
->len
;
2292 if (ret_len
> 0 || len
> 0) {
2293 if (len
>= DHD_IOCTL_MAXLEN
) {
2294 WL_ERR(("oversize input buffer %d\n", len
));
2295 len
= DHD_IOCTL_MAXLEN
- 1;
2297 if (ret_len
>= DHD_IOCTL_MAXLEN
) {
2298 WL_ERR(("oversize return buffer %d\n", ret_len
));
2299 ret_len
= DHD_IOCTL_MAXLEN
- 1;
2302 payload
= max(ret_len
, len
) + 1;
2303 buf
= vzalloc(payload
);
2307 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
2308 #pragma GCC diagnostic push
2309 #pragma GCC diagnostic ignored "-Wcast-qual"
2311 memcpy(buf
, (void *)((char *)nlioc
+ nlioc
->offset
), len
);
2312 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
2313 #pragma GCC diagnostic pop
2315 *((char *)buf
+ len
) = '\0';
2318 ret
= dhd_cfgvendor_priv_string_handler(cfg
, wdev
, nlioc
, buf
);
2320 WL_ERR(("dhd_cfgvendor returned error %d", ret
));
2325 while (ret_len
> 0) {
2326 msglen
= ret_len
> maxmsglen
? maxmsglen
: ret_len
;
2328 payload
= msglen
+ sizeof(msglen
);
2329 reply
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, payload
);
2331 WL_ERR(("Failed to allocate reply msg\n"));
2336 if (nla_put(reply
, BCM_NLATTR_DATA
, msglen
, cur
) ||
2337 nla_put_u16(reply
, BCM_NLATTR_LEN
, msglen
)) {
2343 ret
= cfg80211_vendor_cmd_reply(reply
);
2345 WL_ERR(("testmode reply failed:%d\n", ret
));
2348 cur
= (void *)((char *)cur
+ msglen
);
2355 wl_cfgvendor_get_ndev(struct bcm_cfg80211
*cfg
, struct wireless_dev
*wdev
,
2356 const char *data
, unsigned long int *out_addr
)
2359 char ifname
[IFNAMSIZ
+ 1] = {0};
2360 struct net_info
*iter
, *next
;
2361 struct net_device
*ndev
= NULL
;
2363 *out_addr
= (unsigned long int) data
; /* point to command str by default */
2365 /* check whether ifname=<ifname> is provided in the command */
2366 pos
= strstr(data
, "ifname=");
2368 pos
+= strlen("ifname=");
2369 pos1
= strstr(pos
, " ");
2371 WL_ERR(("command format error \n"));
2375 ifname_len
= pos1
- pos
;
2376 if (memcpy(ifname
, pos
, ifname_len
) != BCME_OK
) {
2377 WL_ERR(("Failed to copy data. len: %d\n", ifname_len
));
2380 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
2381 #pragma GCC diagnostic push
2382 #pragma GCC diagnostic ignored "-Wcast-qual"
2384 for_each_ndev(cfg
, iter
, next
) {
2386 if (strncmp(iter
->ndev
->name
, ifname
,
2387 strlen(iter
->ndev
->name
)) == 0) {
2388 /* matching ifname found */
2389 WL_DBG(("matching interface (%s) found ndev:%p \n",
2390 iter
->ndev
->name
, iter
->ndev
));
2391 *out_addr
= (unsigned long int)(pos1
+ 1);
2392 /* Returns the command portion after ifname=<name> */
2397 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
2398 #pragma GCC diagnostic pop
2400 WL_ERR(("Couldn't find ifname:%s in the netinfo list \n",
2405 /* If ifname=<name> arg is not provided, use default ndev */
2406 ndev
= wdev
->netdev
? wdev
->netdev
: bcmcfg_to_prmry_ndev(cfg
);
2407 WL_DBG(("Using default ndev (%s) \n", ndev
->name
));
2411 /* Max length for the reply buffer. For BRCM_ATTR_DRIVER_CMD, the reply
2412 * would be a formatted string and reply buf would be the size of the
2415 #define WL_DRIVER_PRIV_CMD_LEN 512
2417 #ifdef BCM_PRIV_CMD_SUPPORT
2418 /* strlen("ifname=") + IFNAMESIZE + strlen(" ") + '\0' */
2419 #define ANDROID_PRIV_CMD_IF_PREFIX_LEN (7 + IFNAMSIZ + 2)
2421 wl_cfgvendor_priv_bcm_handler(struct wiphy
*wiphy
,
2422 struct wireless_dev
*wdev
, const void *data
, int len
)
2424 const struct nlattr
*iter
;
2426 int data_len
= 0, cmd_len
= 0, tmp
= 0, type
= 0;
2427 struct net_device
*ndev
= wdev
->netdev
;
2428 char *reply_buf
= NULL
;
2430 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
2432 struct net_device
*net
= NULL
;
2433 unsigned long int cmd_out
= 0;
2434 u32 reply_len
= WL_DRIVER_PRIV_CMD_LEN
;
2436 WL_DBG(("%s: Enter \n", __func__
));
2438 /* hold wake lock */
2439 net_os_wake_lock(ndev
);
2441 nla_for_each_attr(iter
, data
, len
, tmp
) {
2442 type
= nla_type(iter
);
2443 cmd
= nla_data(iter
);
2444 cmd_len
= nla_len(iter
);
2446 WL_DBG(("%s: type: %d cmd_len:%d cmd_ptr:%p \n", __func__
, type
, cmd_len
, cmd
));
2447 if (!cmd
|| !cmd_len
) {
2448 WL_ERR(("Invalid cmd data \n"));
2453 #if defined(WL_ANDROID_PRIV_CMD_OVER_NL80211)
2454 if (type
== BRCM_ATTR_DRIVER_CMD
) {
2455 if ((cmd_len
>= WL_DRIVER_PRIV_CMD_LEN
) ||
2456 (cmd_len
< ANDROID_PRIV_CMD_IF_PREFIX_LEN
)) {
2457 WL_ERR(("Unexpected command length (%u). Ignore the command\n",
2463 /* check whether there is any ifname prefix provided */
2464 if (memcpy(cmd_prefix
, cmd
, ANDROID_PRIV_CMD_IF_PREFIX_LEN
) != BCME_OK
) {
2465 WL_ERR(("memcpy failed for cmd buffer. len:%d\n", cmd_len
));
2470 net
= wl_cfgvendor_get_ndev(cfg
, wdev
, cmd_prefix
, &cmd_out
);
2471 if (!cmd_out
|| !net
) {
2472 WL_ERR(("ndev not found\n"));
2477 /* find offset of the command */
2478 current_pos
= (char *)cmd_out
;
2479 cmd_offset
= current_pos
- cmd_prefix
;
2481 if (!current_pos
|| (cmd_offset
) > ANDROID_PRIV_CMD_IF_PREFIX_LEN
) {
2482 WL_ERR(("Invalid len cmd_offset: %u \n", cmd_offset
));
2487 /* Private command data in expected to be in str format. To ensure that
2488 * the data is null terminated, copy to a local buffer before use
2490 cmd_buf
= (char *)MALLOCZ(cfg
->osh
, cmd_buf_len
);
2492 WL_ERR(("memory alloc failed for %u \n", cmd_buf_len
));
2497 /* Point to the start of command */
2498 if (memcpy(cmd_buf
, (const void *)(cmd
+ cmd_offset
),
2499 (cmd_len
- cmd_offset
- 1)) != BCME_OK
) {
2500 WL_ERR(("memcpy failed for cmd buffer. len:%d\n", cmd_len
));
2504 cmd_buf
[WL_DRIVER_PRIV_CMD_LEN
- 1] = '\0';
2506 WL_DBG(("vendor_command: %s len: %u \n", cmd_buf
, cmd_buf_len
));
2507 bytes_written
= wl_handle_private_cmd(net
, cmd_buf
, cmd_buf_len
);
2508 WL_DBG(("bytes_written: %d \n", bytes_written
));
2509 if (bytes_written
== 0) {
2510 snprintf(cmd_buf
, cmd_buf_len
, "%s", "OK");
2511 data_len
= strlen("OK");
2512 } else if (bytes_written
> 0) {
2513 if (bytes_written
>= (cmd_buf_len
- 1)) {
2519 data_len
= bytes_written
;
2521 /* -ve return value. Propagate the error back */
2522 err
= bytes_written
;
2525 if ((data_len
> 0) && (data_len
< (cmd_buf_len
- 1)) && cmd_buf
) {
2526 err
= wl_cfgvendor_send_cmd_reply(wiphy
, cmd_buf
, data_len
+1);
2527 if (unlikely(err
)) {
2528 WL_ERR(("Vendor Command reply failed ret:%d \n", err
));
2530 WL_DBG(("Vendor Command reply sent successfully!\n"));
2533 /* No data to be sent back as reply */
2534 WL_ERR(("Vendor_cmd: No reply expected. data_len:%u cmd_buf %p \n",
2535 data_len
, cmd_buf
));
2539 #endif /* WL_ANDROID_PRIV_CMD_OVER_NL80211 && OEM_ANDROID */
2543 #if defined(WL_ANDROID_PRIV_CMD_OVER_NL80211)
2545 MFREE(cfg
->osh
, cmd_buf
, cmd_buf_len
);
2547 #endif /* WL_ANDROID_PRIV_CMD_OVER_NL80211 && OEM_ANDROID */
2548 net_os_wake_unlock(ndev
);
2551 #endif /* BCM_PRIV_CMD_SUPPORT */
2554 static const char *nan_attr_to_str(u16 cmd
)
2557 C2S(NAN_ATTRIBUTE_HEADER
)
2558 C2S(NAN_ATTRIBUTE_HANDLE
)
2559 C2S(NAN_ATTRIBUTE_TRANSAC_ID
)
2560 C2S(NAN_ATTRIBUTE_2G_SUPPORT
)
2561 C2S(NAN_ATTRIBUTE_SDF_2G_SUPPORT
)
2562 C2S(NAN_ATTRIBUTE_SDF_5G_SUPPORT
)
2563 C2S(NAN_ATTRIBUTE_5G_SUPPORT
)
2564 C2S(NAN_ATTRIBUTE_SYNC_DISC_2G_BEACON
)
2565 C2S(NAN_ATTRIBUTE_SYNC_DISC_5G_BEACON
)
2566 C2S(NAN_ATTRIBUTE_CLUSTER_LOW
)
2567 C2S(NAN_ATTRIBUTE_CLUSTER_HIGH
)
2568 C2S(NAN_ATTRIBUTE_SID_BEACON
)
2569 C2S(NAN_ATTRIBUTE_RSSI_CLOSE
)
2570 C2S(NAN_ATTRIBUTE_RSSI_MIDDLE
)
2571 C2S(NAN_ATTRIBUTE_RSSI_PROXIMITY
)
2572 C2S(NAN_ATTRIBUTE_RSSI_CLOSE_5G
)
2573 C2S(NAN_ATTRIBUTE_RSSI_MIDDLE_5G
)
2574 C2S(NAN_ATTRIBUTE_RSSI_PROXIMITY_5G
)
2575 C2S(NAN_ATTRIBUTE_HOP_COUNT_LIMIT
)
2576 C2S(NAN_ATTRIBUTE_RANDOM_TIME
)
2577 C2S(NAN_ATTRIBUTE_MASTER_PREF
)
2578 C2S(NAN_ATTRIBUTE_PERIODIC_SCAN_INTERVAL
)
2579 C2S(NAN_ATTRIBUTE_PUBLISH_ID
)
2580 C2S(NAN_ATTRIBUTE_TTL
)
2581 C2S(NAN_ATTRIBUTE_PERIOD
)
2582 C2S(NAN_ATTRIBUTE_REPLIED_EVENT_FLAG
)
2583 C2S(NAN_ATTRIBUTE_PUBLISH_TYPE
)
2584 C2S(NAN_ATTRIBUTE_TX_TYPE
)
2585 C2S(NAN_ATTRIBUTE_PUBLISH_COUNT
)
2586 C2S(NAN_ATTRIBUTE_SERVICE_NAME_LEN
)
2587 C2S(NAN_ATTRIBUTE_SERVICE_NAME
)
2588 C2S(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN
)
2589 C2S(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO
)
2590 C2S(NAN_ATTRIBUTE_RX_MATCH_FILTER_LEN
)
2591 C2S(NAN_ATTRIBUTE_RX_MATCH_FILTER
)
2592 C2S(NAN_ATTRIBUTE_TX_MATCH_FILTER_LEN
)
2593 C2S(NAN_ATTRIBUTE_TX_MATCH_FILTER
)
2594 C2S(NAN_ATTRIBUTE_SUBSCRIBE_ID
)
2595 C2S(NAN_ATTRIBUTE_SUBSCRIBE_TYPE
)
2596 C2S(NAN_ATTRIBUTE_SERVICERESPONSEFILTER
)
2597 C2S(NAN_ATTRIBUTE_SERVICERESPONSEINCLUDE
)
2598 C2S(NAN_ATTRIBUTE_USESERVICERESPONSEFILTER
)
2599 C2S(NAN_ATTRIBUTE_SSIREQUIREDFORMATCHINDICATION
)
2600 C2S(NAN_ATTRIBUTE_SUBSCRIBE_MATCH
)
2601 C2S(NAN_ATTRIBUTE_SUBSCRIBE_COUNT
)
2602 C2S(NAN_ATTRIBUTE_MAC_ADDR
)
2603 C2S(NAN_ATTRIBUTE_MAC_ADDR_LIST
)
2604 C2S(NAN_ATTRIBUTE_MAC_ADDR_LIST_NUM_ENTRIES
)
2605 C2S(NAN_ATTRIBUTE_PUBLISH_MATCH
)
2606 C2S(NAN_ATTRIBUTE_ENABLE_STATUS
)
2607 C2S(NAN_ATTRIBUTE_JOIN_STATUS
)
2608 C2S(NAN_ATTRIBUTE_ROLE
)
2609 C2S(NAN_ATTRIBUTE_MASTER_RANK
)
2610 C2S(NAN_ATTRIBUTE_ANCHOR_MASTER_RANK
)
2611 C2S(NAN_ATTRIBUTE_CNT_PEND_TXFRM
)
2612 C2S(NAN_ATTRIBUTE_CNT_BCN_TX
)
2613 C2S(NAN_ATTRIBUTE_CNT_BCN_RX
)
2614 C2S(NAN_ATTRIBUTE_CNT_SVC_DISC_TX
)
2615 C2S(NAN_ATTRIBUTE_CNT_SVC_DISC_RX
)
2616 C2S(NAN_ATTRIBUTE_AMBTT
)
2617 C2S(NAN_ATTRIBUTE_CLUSTER_ID
)
2618 C2S(NAN_ATTRIBUTE_INST_ID
)
2619 C2S(NAN_ATTRIBUTE_OUI
)
2620 C2S(NAN_ATTRIBUTE_STATUS
)
2621 C2S(NAN_ATTRIBUTE_DE_EVENT_TYPE
)
2622 C2S(NAN_ATTRIBUTE_MERGE
)
2623 C2S(NAN_ATTRIBUTE_IFACE
)
2624 C2S(NAN_ATTRIBUTE_CHANNEL
)
2625 C2S(NAN_ATTRIBUTE_24G_CHANNEL
)
2626 C2S(NAN_ATTRIBUTE_5G_CHANNEL
)
2627 C2S(NAN_ATTRIBUTE_PEER_ID
)
2628 C2S(NAN_ATTRIBUTE_NDP_ID
)
2629 C2S(NAN_ATTRIBUTE_SECURITY
)
2630 C2S(NAN_ATTRIBUTE_QOS
)
2631 C2S(NAN_ATTRIBUTE_RSP_CODE
)
2632 C2S(NAN_ATTRIBUTE_INST_COUNT
)
2633 C2S(NAN_ATTRIBUTE_PEER_DISC_MAC_ADDR
)
2634 C2S(NAN_ATTRIBUTE_PEER_NDI_MAC_ADDR
)
2635 C2S(NAN_ATTRIBUTE_IF_ADDR
)
2636 C2S(NAN_ATTRIBUTE_WARMUP_TIME
)
2637 C2S(NAN_ATTRIBUTE_RECV_IND_CFG
)
2638 C2S(NAN_ATTRIBUTE_CONNMAP
)
2639 C2S(NAN_ATTRIBUTE_DWELL_TIME
)
2640 C2S(NAN_ATTRIBUTE_SCAN_PERIOD
)
2641 C2S(NAN_ATTRIBUTE_RSSI_WINDOW_SIZE
)
2642 C2S(NAN_ATTRIBUTE_CONF_CLUSTER_VAL
)
2643 C2S(NAN_ATTRIBUTE_CIPHER_SUITE_TYPE
)
2644 C2S(NAN_ATTRIBUTE_KEY_TYPE
)
2645 C2S(NAN_ATTRIBUTE_KEY_LEN
)
2646 C2S(NAN_ATTRIBUTE_SCID
)
2647 C2S(NAN_ATTRIBUTE_SCID_LEN
)
2648 C2S(NAN_ATTRIBUTE_SDE_CONTROL_CONFIG_DP
)
2649 C2S(NAN_ATTRIBUTE_SDE_CONTROL_SECURITY
)
2650 C2S(NAN_ATTRIBUTE_SDE_CONTROL_DP_TYPE
)
2651 C2S(NAN_ATTRIBUTE_SDE_CONTROL_RANGE_SUPPORT
)
2652 C2S(NAN_ATTRIBUTE_NO_CONFIG_AVAIL
)
2653 C2S(NAN_ATTRIBUTE_2G_AWAKE_DW
)
2654 C2S(NAN_ATTRIBUTE_5G_AWAKE_DW
)
2655 C2S(NAN_ATTRIBUTE_RSSI_THRESHOLD_FLAG
)
2656 C2S(NAN_ATTRIBUTE_KEY_DATA
)
2657 C2S(NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN
)
2658 C2S(NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO
)
2659 C2S(NAN_ATTRIBUTE_REASON
)
2660 C2S(NAN_ATTRIBUTE_DISC_IND_CFG
)
2661 C2S(NAN_ATTRIBUTE_DWELL_TIME_5G
)
2662 C2S(NAN_ATTRIBUTE_SCAN_PERIOD_5G
)
2663 C2S(NAN_ATTRIBUTE_SUB_SID_BEACON
)
2665 return "NAN_ATTRIBUTE_UNKNOWN";
2669 nan_hal_status_t nan_status_reasonstr_map
[] = {
2670 {NAN_STATUS_SUCCESS
, "NAN status success"},
2671 {NAN_STATUS_INTERNAL_FAILURE
, "NAN Discovery engine failure"},
2672 {NAN_STATUS_PROTOCOL_FAILURE
, "protocol failure"},
2673 {NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID
, "invalid pub_sub ID"},
2674 {NAN_STATUS_NO_RESOURCE_AVAILABLE
, "No space available"},
2675 {NAN_STATUS_INVALID_PARAM
, "invalid param"},
2676 {NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID
, "invalid req inst id"},
2677 {NAN_STATUS_INVALID_NDP_ID
, "invalid ndp id"},
2678 {NAN_STATUS_NAN_NOT_ALLOWED
, "Nan not allowed"},
2679 {NAN_STATUS_NO_OTA_ACK
, "No OTA ack"},
2680 {NAN_STATUS_ALREADY_ENABLED
, "NAN is Already enabled"},
2681 {NAN_STATUS_FOLLOWUP_QUEUE_FULL
, "Follow-up queue full"},
2682 {NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED
, "unsupported concurrency"},
2686 wl_cfgvendor_add_nan_reason_str(nan_status_type_t status
, nan_hal_resp_t
*nan_req_resp
)
2689 int num
= (int)(sizeof(nan_status_reasonstr_map
)/sizeof(nan_status_reasonstr_map
[0]));
2690 for (i
= 0; i
< num
; i
++) {
2691 if (nan_status_reasonstr_map
[i
].status
== status
) {
2692 strlcpy(nan_req_resp
->nan_reason
, nan_status_reasonstr_map
[i
].nan_reason
,
2693 sizeof(nan_status_reasonstr_map
[i
].nan_reason
));
2700 wl_cfgvendor_brcm_to_nanhal_status(int32 vendor_status
)
2702 nan_status_type_t hal_status
;
2703 switch (vendor_status
) {
2705 hal_status
= NAN_STATUS_SUCCESS
;
2709 hal_status
= NAN_STATUS_NAN_NOT_ALLOWED
;
2713 case BCME_UNSUPPORTED
:
2714 case BCME_USAGE_ERROR
:
2716 hal_status
= NAN_STATUS_INVALID_PARAM
;
2719 case BCME_NORESOURCE
:
2720 case WL_NAN_E_SVC_SUB_LIST_FULL
:
2721 hal_status
= NAN_STATUS_NO_RESOURCE_AVAILABLE
;
2723 case WL_NAN_E_SD_TX_LIST_FULL
:
2724 hal_status
= NAN_STATUS_FOLLOWUP_QUEUE_FULL
;
2726 case WL_NAN_E_BAD_INSTANCE
:
2727 hal_status
= NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID
;
2730 WL_ERR(("%s Unknown vendor status, status = %d\n",
2731 __func__
, vendor_status
));
2733 hal_status
= NAN_STATUS_INTERNAL_FAILURE
;
2739 wl_cfgvendor_nan_cmd_reply(struct wiphy
*wiphy
, int nan_cmd
,
2740 nan_hal_resp_t
*nan_req_resp
, int ret
, int nan_cmd_status
)
2744 nan_req_resp
->subcmd
= nan_cmd
;
2745 if (ret
== BCME_OK
) {
2746 nan_reply
= nan_cmd_status
;
2750 nan_req_resp
->status
= wl_cfgvendor_brcm_to_nanhal_status(nan_reply
);
2751 nan_req_resp
->value
= ret
;
2752 err
= wl_cfgvendor_send_cmd_reply(wiphy
, nan_req_resp
,
2753 sizeof(*nan_req_resp
));
2754 /* giving more prio to ret than err */
2755 return (ret
== 0) ? err
: ret
;
2759 wl_cfgvendor_free_disc_cmd_data(struct bcm_cfg80211
*cfg
,
2760 nan_discover_cmd_data_t
*cmd_data
)
2763 WL_ERR(("Cmd_data is null\n"));
2766 if (cmd_data
->svc_info
.data
) {
2767 MFREE(cfg
->osh
, cmd_data
->svc_info
.data
, cmd_data
->svc_info
.dlen
);
2769 if (cmd_data
->svc_hash
.data
) {
2770 MFREE(cfg
->osh
, cmd_data
->svc_hash
.data
, cmd_data
->svc_hash
.dlen
);
2772 if (cmd_data
->rx_match
.data
) {
2773 MFREE(cfg
->osh
, cmd_data
->rx_match
.data
, cmd_data
->rx_match
.dlen
);
2775 if (cmd_data
->tx_match
.data
) {
2776 MFREE(cfg
->osh
, cmd_data
->tx_match
.data
, cmd_data
->tx_match
.dlen
);
2778 if (cmd_data
->mac_list
.list
) {
2779 MFREE(cfg
->osh
, cmd_data
->mac_list
.list
,
2780 cmd_data
->mac_list
.num_mac_addr
* ETHER_ADDR_LEN
);
2782 if (cmd_data
->key
.data
) {
2783 MFREE(cfg
->osh
, cmd_data
->key
.data
, NAN_MAX_PMK_LEN
);
2785 if (cmd_data
->sde_svc_info
.data
) {
2786 MFREE(cfg
->osh
, cmd_data
->sde_svc_info
.data
, cmd_data
->sde_svc_info
.dlen
);
2788 MFREE(cfg
->osh
, cmd_data
, sizeof(*cmd_data
));
2792 wl_cfgvendor_free_dp_cmd_data(struct bcm_cfg80211
*cfg
,
2793 nan_datapath_cmd_data_t
*cmd_data
)
2796 WL_ERR(("Cmd_data is null\n"));
2799 if (cmd_data
->svc_hash
.data
) {
2800 MFREE(cfg
->osh
, cmd_data
->svc_hash
.data
, cmd_data
->svc_hash
.dlen
);
2802 if (cmd_data
->svc_info
.data
) {
2803 MFREE(cfg
->osh
, cmd_data
->svc_info
.data
, cmd_data
->svc_info
.dlen
);
2805 if (cmd_data
->key
.data
) {
2806 MFREE(cfg
->osh
, cmd_data
->key
.data
, NAN_MAX_PMK_LEN
);
2808 MFREE(cfg
->osh
, cmd_data
, sizeof(*cmd_data
));
2811 #define WL_NAN_EVENT_MAX_BUF 256
2812 #ifdef WL_NAN_DISC_CACHE
2814 wl_cfgvendor_nan_parse_dp_sec_info_args(struct wiphy
*wiphy
,
2815 const void *buf
, int len
, nan_datapath_sec_info_cmd_data_t
*cmd_data
)
2820 const struct nlattr
*iter
;
2824 nla_for_each_attr(iter
, buf
, len
, rem
) {
2825 attr_type
= nla_type(iter
);
2826 WL_TRACE(("attr: %s (%u)\n", nan_attr_to_str(attr_type
), attr_type
));
2828 switch (attr_type
) {
2829 case NAN_ATTRIBUTE_MAC_ADDR
:
2830 memcpy((char*)&cmd_data
->mac_addr
, (char*)nla_data(iter
),
2833 case NAN_ATTRIBUTE_PUBLISH_ID
:
2834 cmd_data
->pub_id
= nla_get_u16(iter
);
2836 case NAN_ATTRIBUTE_NDP_ID
:
2837 cmd_data
->ndp_instance_id
= nla_get_u32(iter
);
2840 WL_ERR(("%s: Unknown type, %d\n", __FUNCTION__
, attr_type
));
2845 /* We need to call set_config_handler b/f calling start enable TBD */
2849 #endif /* WL_NAN_DISC_CACHE */
2851 int8 chanbuf
[CHANSPEC_STR_LEN
];
2853 wl_cfgvendor_nan_parse_datapath_args(struct wiphy
*wiphy
,
2854 const void *buf
, int len
, nan_datapath_cmd_data_t
*cmd_data
)
2859 const struct nlattr
*iter
;
2860 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
2865 nla_for_each_attr(iter
, buf
, len
, rem
) {
2866 attr_type
= nla_type(iter
);
2867 WL_TRACE(("attr: %s (%u)\n", nan_attr_to_str(attr_type
), attr_type
));
2869 switch (attr_type
) {
2870 case NAN_ATTRIBUTE_NDP_ID
:
2871 if (nla_len(iter
) != sizeof(uint32
)) {
2875 cmd_data
->ndp_instance_id
= nla_get_u32(iter
);
2877 case NAN_ATTRIBUTE_IFACE
:
2878 if (nla_len(iter
) >= sizeof(cmd_data
->ndp_iface
)) {
2879 WL_ERR(("iface_name len wrong:%d\n", nla_len(iter
)));
2883 strlcpy((char *)cmd_data
->ndp_iface
, (char *)nla_data(iter
),
2886 case NAN_ATTRIBUTE_SECURITY
:
2887 if (nla_len(iter
) != sizeof(uint8
)) {
2891 cmd_data
->ndp_cfg
.security_cfg
= nla_get_u8(iter
);
2893 case NAN_ATTRIBUTE_QOS
:
2894 if (nla_len(iter
) != sizeof(uint8
)) {
2898 cmd_data
->ndp_cfg
.qos_cfg
= nla_get_u8(iter
);
2900 case NAN_ATTRIBUTE_RSP_CODE
:
2901 if (nla_len(iter
) != sizeof(uint8
)) {
2905 cmd_data
->rsp_code
= nla_get_u8(iter
);
2907 case NAN_ATTRIBUTE_INST_COUNT
:
2908 if (nla_len(iter
) != sizeof(uint8
)) {
2912 cmd_data
->num_ndp_instances
= nla_get_u8(iter
);
2914 case NAN_ATTRIBUTE_PEER_DISC_MAC_ADDR
:
2915 if (nla_len(iter
) != ETHER_ADDR_LEN
) {
2919 memcpy((char*)&cmd_data
->peer_disc_mac_addr
,
2920 (char*)nla_data(iter
), ETHER_ADDR_LEN
);
2922 case NAN_ATTRIBUTE_PEER_NDI_MAC_ADDR
:
2923 if (nla_len(iter
) != ETHER_ADDR_LEN
) {
2927 memcpy((char*)&cmd_data
->peer_ndi_mac_addr
,
2928 (char*)nla_data(iter
), ETHER_ADDR_LEN
);
2930 case NAN_ATTRIBUTE_MAC_ADDR
:
2931 if (nla_len(iter
) != ETHER_ADDR_LEN
) {
2935 memcpy((char*)&cmd_data
->mac_addr
, (char*)nla_data(iter
),
2938 case NAN_ATTRIBUTE_IF_ADDR
:
2939 if (nla_len(iter
) != ETHER_ADDR_LEN
) {
2943 memcpy((char*)&cmd_data
->if_addr
, (char*)nla_data(iter
),
2946 case NAN_ATTRIBUTE_ENTRY_CONTROL
:
2947 if (nla_len(iter
) != sizeof(uint8
)) {
2951 cmd_data
->avail_params
.duration
= nla_get_u8(iter
);
2953 case NAN_ATTRIBUTE_AVAIL_BIT_MAP
:
2954 if (nla_len(iter
) != sizeof(uint32
)) {
2958 cmd_data
->avail_params
.bmap
= nla_get_u32(iter
);
2960 case NAN_ATTRIBUTE_CHANNEL
: {
2961 if (nla_len(iter
) != sizeof(uint32
)) {
2965 /* take the default channel start_factor frequency */
2966 chan
= wf_mhz2channel((uint
)nla_get_u32(iter
), 0);
2967 if (chan
<= CH_MAX_2G_CHANNEL
) {
2968 cmd_data
->avail_params
.chanspec
[0] =
2969 wf_channel2chspec(chan
, WL_CHANSPEC_BW_20
);
2971 cmd_data
->avail_params
.chanspec
[0] =
2972 wf_channel2chspec(chan
, WL_CHANSPEC_BW_80
);
2974 if (cmd_data
->avail_params
.chanspec
[0] == 0) {
2975 WL_ERR(("Channel is not valid \n"));
2979 WL_TRACE(("valid chanspec, chanspec = 0x%04x \n",
2980 cmd_data
->avail_params
.chanspec
[0]));
2983 case NAN_ATTRIBUTE_NO_CONFIG_AVAIL
:
2984 if (nla_len(iter
) != sizeof(uint8
)) {
2988 cmd_data
->avail_params
.no_config_avail
= (bool)nla_get_u8(iter
);
2990 case NAN_ATTRIBUTE_SERVICE_NAME_LEN
: {
2991 if (nla_len(iter
) != sizeof(uint16
)) {
2995 if (cmd_data
->svc_hash
.dlen
) {
2996 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3000 cmd_data
->svc_hash
.dlen
= nla_get_u16(iter
);
3001 if (cmd_data
->svc_hash
.dlen
!= WL_NAN_SVC_HASH_LEN
) {
3002 WL_ERR(("invalid svc_hash length = %u\n", cmd_data
->svc_hash
.dlen
));
3008 case NAN_ATTRIBUTE_SERVICE_NAME
:
3009 if ((!cmd_data
->svc_hash
.dlen
) ||
3010 (nla_len(iter
) != cmd_data
->svc_hash
.dlen
)) {
3011 WL_ERR(("invalid svc_hash length = %d,%d\n",
3012 cmd_data
->svc_hash
.dlen
, nla_len(iter
)));
3016 if (cmd_data
->svc_hash
.data
) {
3017 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3021 cmd_data
->svc_hash
.data
=
3022 MALLOCZ(cfg
->osh
, cmd_data
->svc_hash
.dlen
);
3023 if (!cmd_data
->svc_hash
.data
) {
3024 WL_ERR(("failed to allocate svc_hash data, len=%d\n",
3025 cmd_data
->svc_hash
.dlen
));
3029 memcpy(cmd_data
->svc_hash
.data
, nla_data(iter
),
3030 cmd_data
->svc_hash
.dlen
);
3032 case NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN
:
3033 if (nla_len(iter
) != sizeof(uint16
)) {
3037 if (cmd_data
->svc_info
.dlen
) {
3038 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3042 cmd_data
->svc_info
.dlen
= nla_get_u16(iter
);
3043 if (cmd_data
->svc_info
.dlen
> MAX_APP_INFO_LEN
) {
3044 WL_ERR(("Not allowed beyond :%d\n", MAX_APP_INFO_LEN
));
3049 case NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO
:
3050 if ((!cmd_data
->svc_info
.dlen
) ||
3051 (nla_len(iter
) != cmd_data
->svc_info
.dlen
)) {
3052 WL_ERR(("failed to allocate svc info by invalid len=%d,%d\n",
3053 cmd_data
->svc_info
.dlen
, nla_len(iter
)));
3057 if (cmd_data
->svc_info
.data
) {
3058 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3062 cmd_data
->svc_info
.data
= MALLOCZ(cfg
->osh
, cmd_data
->svc_info
.dlen
);
3063 if (cmd_data
->svc_info
.data
== NULL
) {
3064 WL_ERR(("failed to allocate svc info data, len=%d\n",
3065 cmd_data
->svc_info
.dlen
));
3069 memcpy(cmd_data
->svc_info
.data
,
3070 nla_data(iter
), cmd_data
->svc_info
.dlen
);
3072 case NAN_ATTRIBUTE_PUBLISH_ID
:
3073 if (nla_len(iter
) != sizeof(uint32
)) {
3077 cmd_data
->pub_id
= nla_get_u32(iter
);
3079 case NAN_ATTRIBUTE_CIPHER_SUITE_TYPE
:
3080 if (nla_len(iter
) != sizeof(uint8
)) {
3084 cmd_data
->csid
= nla_get_u8(iter
);
3085 WL_TRACE(("CSID = %u\n", cmd_data
->csid
));
3087 case NAN_ATTRIBUTE_KEY_TYPE
:
3088 if (nla_len(iter
) != sizeof(uint8
)) {
3092 cmd_data
->key_type
= nla_get_u8(iter
);
3093 WL_TRACE(("Key Type = %u\n", cmd_data
->key_type
));
3095 case NAN_ATTRIBUTE_KEY_LEN
:
3096 if (nla_len(iter
) != sizeof(uint32
)) {
3100 if (cmd_data
->key
.dlen
) {
3101 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3105 cmd_data
->key
.dlen
= nla_get_u32(iter
);
3106 if ((!cmd_data
->key
.dlen
) || (cmd_data
->key
.dlen
> WL_NAN_NCS_SK_PMK_LEN
)) {
3107 WL_ERR(("invalid key length = %u\n", cmd_data
->key
.dlen
));
3111 WL_TRACE(("valid key length = %u\n", cmd_data
->key
.dlen
));
3113 case NAN_ATTRIBUTE_KEY_DATA
:
3114 if ((!cmd_data
->key
.dlen
) ||
3115 (nla_len(iter
) != cmd_data
->key
.dlen
)) {
3116 WL_ERR(("failed to allocate key data by invalid len=%d,%d\n",
3117 cmd_data
->key
.dlen
, nla_len(iter
)));
3121 if (cmd_data
->key
.data
) {
3122 WL_ERR(("trying to overwrite key data.\n"));
3127 cmd_data
->key
.data
= MALLOCZ(cfg
->osh
, NAN_MAX_PMK_LEN
);
3128 if (cmd_data
->key
.data
== NULL
) {
3129 WL_ERR(("failed to allocate key data, len=%d\n",
3130 cmd_data
->key
.dlen
));
3134 memcpy(cmd_data
->key
.data
, nla_data(iter
),
3135 MIN(cmd_data
->key
.dlen
, NAN_MAX_PMK_LEN
));
3139 WL_ERR(("Unknown type, %d\n", attr_type
));
3145 /* We need to call set_config_handler b/f calling start enable TBD */
3151 wl_cfgvendor_nan_parse_discover_args(struct wiphy
*wiphy
,
3152 const void *buf
, int len
, nan_discover_cmd_data_t
*cmd_data
)
3157 const struct nlattr
*iter
;
3158 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
3165 nla_for_each_attr(iter
, buf
, len
, rem
) {
3166 attr_type
= nla_type(iter
);
3167 WL_TRACE(("attr: %s (%u)\n", nan_attr_to_str(attr_type
), attr_type
));
3169 switch (attr_type
) {
3170 case NAN_ATTRIBUTE_TRANSAC_ID
:
3171 if (nla_len(iter
) != sizeof(uint16
)) {
3175 cmd_data
->token
= nla_get_u16(iter
);
3177 case NAN_ATTRIBUTE_PERIODIC_SCAN_INTERVAL
:
3180 /* Nan Publish/Subscribe request Attributes */
3181 case NAN_ATTRIBUTE_PUBLISH_ID
:
3182 if (nla_len(iter
) != sizeof(uint16
)) {
3186 cmd_data
->pub_id
= nla_get_u16(iter
);
3187 cmd_data
->local_id
= cmd_data
->pub_id
;
3189 case NAN_ATTRIBUTE_MAC_ADDR
:
3190 if (nla_len(iter
) != ETHER_ADDR_LEN
) {
3194 memcpy((char*)&cmd_data
->mac_addr
, (char*)nla_data(iter
),
3197 case NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN
:
3198 if (nla_len(iter
) != sizeof(uint16
)) {
3202 if (cmd_data
->svc_info
.dlen
) {
3203 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3207 cmd_data
->svc_info
.dlen
= nla_get_u16(iter
);
3208 if (cmd_data
->svc_info
.dlen
> NAN_MAX_SERVICE_SPECIFIC_INFO_LEN
) {
3209 WL_ERR(("Not allowed beyond :%d\n",
3210 NAN_MAX_SERVICE_SPECIFIC_INFO_LEN
));
3215 case NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO
:
3216 if ((!cmd_data
->svc_info
.dlen
) ||
3217 (nla_len(iter
) != cmd_data
->svc_info
.dlen
)) {
3218 WL_ERR(("failed to allocate svc info by invalid len=%d,%d\n",
3219 cmd_data
->svc_info
.dlen
, nla_len(iter
)));
3223 if (cmd_data
->svc_info
.data
) {
3224 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3229 cmd_data
->svc_info
.data
= MALLOCZ(cfg
->osh
, cmd_data
->svc_info
.dlen
);
3230 if (cmd_data
->svc_info
.data
== NULL
) {
3231 WL_ERR(("failed to allocate svc info data, len=%d\n",
3232 cmd_data
->svc_info
.dlen
));
3236 memcpy(cmd_data
->svc_info
.data
,
3237 nla_data(iter
), cmd_data
->svc_info
.dlen
);
3239 case NAN_ATTRIBUTE_SUBSCRIBE_ID
:
3240 if (nla_len(iter
) != sizeof(uint16
)) {
3244 cmd_data
->sub_id
= nla_get_u16(iter
);
3245 cmd_data
->local_id
= cmd_data
->sub_id
;
3247 case NAN_ATTRIBUTE_SUBSCRIBE_TYPE
:
3248 if (nla_len(iter
) != sizeof(uint8
)) {
3252 cmd_data
->flags
|= nla_get_u8(iter
) ? WL_NAN_SUB_ACTIVE
: 0;
3254 case NAN_ATTRIBUTE_PUBLISH_COUNT
:
3255 if (nla_len(iter
) != sizeof(uint8
)) {
3259 cmd_data
->life_count
= nla_get_u8(iter
);
3261 case NAN_ATTRIBUTE_PUBLISH_TYPE
: {
3262 if (nla_len(iter
) != sizeof(uint8
)) {
3266 val_u8
= nla_get_u8(iter
);
3268 cmd_data
->flags
|= WL_NAN_PUB_UNSOLICIT
;
3269 } else if (val_u8
== 1) {
3270 cmd_data
->flags
|= WL_NAN_PUB_SOLICIT
;
3272 cmd_data
->flags
|= WL_NAN_PUB_BOTH
;
3276 case NAN_ATTRIBUTE_PERIOD
: {
3277 if (nla_len(iter
) != sizeof(uint16
)) {
3281 if (nla_get_u16(iter
) > NAN_MAX_AWAKE_DW_INTERVAL
) {
3282 WL_ERR(("Invalid/Out of bound value = %u\n", nla_get_u16(iter
)));
3286 if (nla_get_u16(iter
)) {
3287 cmd_data
->period
= 1 << (nla_get_u16(iter
)-1);
3291 case NAN_ATTRIBUTE_REPLIED_EVENT_FLAG
:
3293 case NAN_ATTRIBUTE_TTL
:
3294 if (nla_len(iter
) != sizeof(uint16
)) {
3298 cmd_data
->ttl
= nla_get_u16(iter
);
3300 case NAN_ATTRIBUTE_SERVICE_NAME_LEN
: {
3301 if (nla_len(iter
) != sizeof(uint16
)) {
3305 if (cmd_data
->svc_hash
.dlen
) {
3306 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3311 cmd_data
->svc_hash
.dlen
= nla_get_u16(iter
);
3312 if (cmd_data
->svc_hash
.dlen
!= WL_NAN_SVC_HASH_LEN
) {
3313 WL_ERR(("invalid svc_hash length = %u\n", cmd_data
->svc_hash
.dlen
));
3319 case NAN_ATTRIBUTE_SERVICE_NAME
:
3320 if ((!cmd_data
->svc_hash
.dlen
) ||
3321 (nla_len(iter
) != cmd_data
->svc_hash
.dlen
)) {
3322 WL_ERR(("invalid svc_hash length = %d,%d\n",
3323 cmd_data
->svc_hash
.dlen
, nla_len(iter
)));
3327 if (cmd_data
->svc_hash
.data
) {
3328 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3333 cmd_data
->svc_hash
.data
=
3334 MALLOCZ(cfg
->osh
, cmd_data
->svc_hash
.dlen
);
3335 if (!cmd_data
->svc_hash
.data
) {
3336 WL_ERR(("failed to allocate svc_hash data, len=%d\n",
3337 cmd_data
->svc_hash
.dlen
));
3341 memcpy(cmd_data
->svc_hash
.data
, nla_data(iter
),
3342 cmd_data
->svc_hash
.dlen
);
3344 case NAN_ATTRIBUTE_PEER_ID
:
3345 if (nla_len(iter
) != sizeof(uint32
)) {
3349 cmd_data
->remote_id
= nla_get_u32(iter
);
3351 case NAN_ATTRIBUTE_INST_ID
:
3352 if (nla_len(iter
) != sizeof(uint16
)) {
3356 cmd_data
->local_id
= nla_get_u16(iter
);
3358 case NAN_ATTRIBUTE_SUBSCRIBE_COUNT
:
3359 if (nla_len(iter
) != sizeof(uint8
)) {
3363 cmd_data
->life_count
= nla_get_u8(iter
);
3365 case NAN_ATTRIBUTE_SSIREQUIREDFORMATCHINDICATION
: {
3366 if (nla_len(iter
) != sizeof(uint8
)) {
3370 bit_flag
= (u32
)nla_get_u8(iter
);
3372 bit_flag
? WL_NAN_SUB_MATCH_IF_SVC_INFO
: 0;
3375 case NAN_ATTRIBUTE_SUBSCRIBE_MATCH
:
3376 case NAN_ATTRIBUTE_PUBLISH_MATCH
: {
3377 if (nla_len(iter
) != sizeof(uint8
)) {
3381 flag_match
= nla_get_u8(iter
);
3383 switch (flag_match
) {
3384 case NAN_MATCH_ALG_MATCH_CONTINUOUS
:
3385 /* Default fw behaviour, no need to set explicitly */
3387 case NAN_MATCH_ALG_MATCH_ONCE
:
3388 cmd_data
->flags
|= WL_NAN_MATCH_ONCE
;
3390 case NAN_MATCH_ALG_MATCH_NEVER
:
3391 cmd_data
->flags
|= WL_NAN_MATCH_NEVER
;
3394 WL_ERR(("invalid nan match alg = %u\n", flag_match
));
3400 case NAN_ATTRIBUTE_SERVICERESPONSEFILTER
:
3401 if (nla_len(iter
) != sizeof(uint8
)) {
3405 cmd_data
->srf_type
= nla_get_u8(iter
);
3407 case NAN_ATTRIBUTE_SERVICERESPONSEINCLUDE
:
3408 if (nla_len(iter
) != sizeof(uint8
)) {
3412 cmd_data
->srf_include
= nla_get_u8(iter
);
3414 case NAN_ATTRIBUTE_USESERVICERESPONSEFILTER
:
3415 if (nla_len(iter
) != sizeof(uint8
)) {
3419 cmd_data
->use_srf
= nla_get_u8(iter
);
3421 case NAN_ATTRIBUTE_RX_MATCH_FILTER_LEN
:
3422 if (nla_len(iter
) != sizeof(uint16
)) {
3426 if (cmd_data
->rx_match
.dlen
) {
3427 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3431 cmd_data
->rx_match
.dlen
= nla_get_u16(iter
);
3432 if (cmd_data
->rx_match
.dlen
> MAX_MATCH_FILTER_LEN
) {
3434 WL_ERR(("Not allowed beyond %d\n", MAX_MATCH_FILTER_LEN
));
3438 case NAN_ATTRIBUTE_RX_MATCH_FILTER
:
3439 if ((!cmd_data
->rx_match
.dlen
) ||
3440 (nla_len(iter
) != cmd_data
->rx_match
.dlen
)) {
3441 WL_ERR(("RX match filter len wrong:%d,%d\n",
3442 cmd_data
->rx_match
.dlen
, nla_len(iter
)));
3446 if (cmd_data
->rx_match
.data
) {
3447 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3451 cmd_data
->rx_match
.data
=
3452 MALLOCZ(cfg
->osh
, cmd_data
->rx_match
.dlen
);
3453 if (cmd_data
->rx_match
.data
== NULL
) {
3454 WL_ERR(("failed to allocate LEN=[%u]\n",
3455 cmd_data
->rx_match
.dlen
));
3459 memcpy(cmd_data
->rx_match
.data
, nla_data(iter
),
3460 cmd_data
->rx_match
.dlen
);
3462 case NAN_ATTRIBUTE_TX_MATCH_FILTER_LEN
:
3463 if (nla_len(iter
) != sizeof(uint16
)) {
3467 if (cmd_data
->tx_match
.dlen
) {
3468 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3472 cmd_data
->tx_match
.dlen
= nla_get_u16(iter
);
3473 if (cmd_data
->tx_match
.dlen
> MAX_MATCH_FILTER_LEN
) {
3475 WL_ERR(("Not allowed beyond %d\n", MAX_MATCH_FILTER_LEN
));
3479 case NAN_ATTRIBUTE_TX_MATCH_FILTER
:
3480 if ((!cmd_data
->tx_match
.dlen
) ||
3481 (nla_len(iter
) != cmd_data
->tx_match
.dlen
)) {
3482 WL_ERR(("TX match filter len wrong:%d,%d\n",
3483 cmd_data
->tx_match
.dlen
, nla_len(iter
)));
3487 if (cmd_data
->tx_match
.data
) {
3488 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3492 cmd_data
->tx_match
.data
=
3493 MALLOCZ(cfg
->osh
, cmd_data
->tx_match
.dlen
);
3494 if (cmd_data
->tx_match
.data
== NULL
) {
3495 WL_ERR(("failed to allocate LEN=[%u]\n",
3496 cmd_data
->tx_match
.dlen
));
3500 memcpy(cmd_data
->tx_match
.data
, nla_data(iter
),
3501 cmd_data
->tx_match
.dlen
);
3503 case NAN_ATTRIBUTE_MAC_ADDR_LIST_NUM_ENTRIES
:
3504 if (nla_len(iter
) != sizeof(uint16
)) {
3508 if (cmd_data
->mac_list
.num_mac_addr
) {
3509 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3513 cmd_data
->mac_list
.num_mac_addr
= nla_get_u16(iter
);
3515 case NAN_ATTRIBUTE_MAC_ADDR_LIST
:
3516 if ((!cmd_data
->mac_list
.num_mac_addr
) ||
3517 (nla_len(iter
) != (cmd_data
->mac_list
.num_mac_addr
* ETHER_ADDR_LEN
))) {
3518 WL_ERR(("wrong mac list len:%d,%d\n",
3519 cmd_data
->mac_list
.num_mac_addr
, nla_len(iter
)));
3523 if (cmd_data
->mac_list
.list
) {
3524 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3528 cmd_data
->mac_list
.list
=
3529 MALLOCZ(cfg
->osh
, (cmd_data
->mac_list
.num_mac_addr
3531 if (cmd_data
->mac_list
.list
== NULL
) {
3532 WL_ERR(("failed to allocate LEN=[%u]\n",
3533 (cmd_data
->mac_list
.num_mac_addr
* ETHER_ADDR_LEN
)));
3537 memcpy(cmd_data
->mac_list
.list
, nla_data(iter
),
3538 (cmd_data
->mac_list
.num_mac_addr
* ETHER_ADDR_LEN
));
3540 case NAN_ATTRIBUTE_TX_TYPE
:
3541 if (nla_len(iter
) != sizeof(uint8
)) {
3545 val_u8
= nla_get_u8(iter
);
3547 cmd_data
->flags
|= WL_NAN_PUB_BCAST
;
3548 WL_TRACE(("NAN_ATTRIBUTE_TX_TYPE: flags=NAN_PUB_BCAST\n"));
3551 case NAN_ATTRIBUTE_SDE_CONTROL_CONFIG_DP
:
3552 if (nla_len(iter
) != sizeof(uint8
)) {
3556 if (nla_get_u8(iter
) == 1) {
3557 cmd_data
->sde_control_flag
3558 |= NAN_SDE_CF_DP_REQUIRED
;
3562 case NAN_ATTRIBUTE_SDE_CONTROL_RANGE_SUPPORT
:
3563 if (nla_len(iter
) != sizeof(uint8
)) {
3567 if (nla_get_u8(iter
) == 1) {
3568 cmd_data
->sde_control_flag
3569 |= NAN_SDE_CF_RANGING_REQUIRED
;
3573 case NAN_ATTRIBUTE_SDE_CONTROL_DP_TYPE
:
3574 if (nla_len(iter
) != sizeof(uint8
)) {
3578 if (nla_get_u8(iter
) == 1) {
3579 cmd_data
->sde_control_flag
3580 |= NAN_SDE_CF_MULTICAST_TYPE
;
3584 case NAN_ATTRIBUTE_SDE_CONTROL_SECURITY
:
3585 if (nla_len(iter
) != sizeof(uint8
)) {
3589 if (nla_get_u8(iter
) == 1) {
3590 cmd_data
->sde_control_flag
3591 |= NAN_SDE_CF_SECURITY_REQUIRED
;
3595 case NAN_ATTRIBUTE_RECV_IND_CFG
:
3596 if (nla_len(iter
) != sizeof(uint8
)) {
3600 cmd_data
->recv_ind_flag
= nla_get_u8(iter
);
3602 case NAN_ATTRIBUTE_CIPHER_SUITE_TYPE
:
3603 if (nla_len(iter
) != sizeof(uint8
)) {
3607 cmd_data
->csid
= nla_get_u8(iter
);
3608 WL_TRACE(("CSID = %u\n", cmd_data
->csid
));
3610 case NAN_ATTRIBUTE_KEY_TYPE
:
3611 if (nla_len(iter
) != sizeof(uint8
)) {
3615 cmd_data
->key_type
= nla_get_u8(iter
);
3616 WL_TRACE(("Key Type = %u\n", cmd_data
->key_type
));
3618 case NAN_ATTRIBUTE_KEY_LEN
:
3619 if (nla_len(iter
) != sizeof(uint32
)) {
3623 if (cmd_data
->key
.dlen
) {
3624 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3628 cmd_data
->key
.dlen
= nla_get_u32(iter
);
3629 if ((!cmd_data
->key
.dlen
) || (cmd_data
->key
.dlen
> WL_NAN_NCS_SK_PMK_LEN
)) {
3630 WL_ERR(("invalid key length = %u\n",
3631 cmd_data
->key
.dlen
));
3634 WL_TRACE(("valid key length = %u\n", cmd_data
->key
.dlen
));
3636 case NAN_ATTRIBUTE_KEY_DATA
:
3637 if (!cmd_data
->key
.dlen
||
3638 (nla_len(iter
) != cmd_data
->key
.dlen
)) {
3639 WL_ERR(("failed to allocate key data by invalid len=%d,%d\n",
3640 cmd_data
->key
.dlen
, nla_len(iter
)));
3644 if (cmd_data
->key
.data
) {
3645 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3650 cmd_data
->key
.data
= MALLOCZ(cfg
->osh
, NAN_MAX_PMK_LEN
);
3651 if (cmd_data
->key
.data
== NULL
) {
3652 WL_ERR(("failed to allocate key data, len=%d\n",
3653 cmd_data
->key
.dlen
));
3657 memcpy(cmd_data
->key
.data
, nla_data(iter
),
3658 MIN(cmd_data
->key
.dlen
, NAN_MAX_PMK_LEN
));
3660 case NAN_ATTRIBUTE_RSSI_THRESHOLD_FLAG
:
3661 if (nla_len(iter
) != sizeof(uint8
)) {
3665 if (nla_get_u8(iter
) == 1) {
3667 WL_NAN_RANGE_LIMITED
;
3671 case NAN_ATTRIBUTE_DISC_IND_CFG
:
3672 if (nla_len(iter
) != sizeof(uint8
)) {
3676 cmd_data
->disc_ind_cfg
= nla_get_u8(iter
);
3678 case NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN
:
3679 if (nla_len(iter
) != sizeof(uint16
)) {
3683 if (cmd_data
->sde_svc_info
.dlen
) {
3684 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3688 cmd_data
->sde_svc_info
.dlen
= nla_get_u16(iter
);
3689 if (cmd_data
->sde_svc_info
.dlen
> MAX_SDEA_SVC_INFO_LEN
) {
3691 WL_ERR(("Not allowed beyond %d\n", MAX_SDEA_SVC_INFO_LEN
));
3695 case NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO
:
3696 if ((!cmd_data
->sde_svc_info
.dlen
) ||
3697 (nla_len(iter
) != cmd_data
->sde_svc_info
.dlen
)) {
3698 WL_ERR(("wrong sdea info len:%d,%d\n",
3699 cmd_data
->sde_svc_info
.dlen
, nla_len(iter
)));
3703 if (cmd_data
->sde_svc_info
.data
) {
3704 WL_ERR(("trying to overwrite:%d\n", attr_type
));
3708 cmd_data
->sde_svc_info
.data
= MALLOCZ(cfg
->osh
,
3709 cmd_data
->sde_svc_info
.dlen
);
3710 if (cmd_data
->sde_svc_info
.data
== NULL
) {
3711 WL_ERR(("failed to allocate svc info data, len=%d\n",
3712 cmd_data
->sde_svc_info
.dlen
));
3716 memcpy(cmd_data
->sde_svc_info
.data
,
3717 nla_data(iter
), cmd_data
->sde_svc_info
.dlen
);
3719 case NAN_ATTRIBUTE_SECURITY
:
3720 if (nla_len(iter
) != sizeof(uint8
)) {
3724 cmd_data
->ndp_cfg
.security_cfg
= nla_get_u8(iter
);
3726 case NAN_ATTRIBUTE_RANGING_INTERVAL
:
3727 if (nla_len(iter
) != sizeof(uint32
)) {
3731 cmd_data
->ranging_intvl_msec
= nla_get_u32(iter
);
3733 case NAN_ATTRIBUTE_RANGING_INGRESS_LIMIT
:
3734 if (nla_len(iter
) != sizeof(uint32
)) {
3738 cmd_data
->ingress_limit
= nla_get_u32(iter
);
3740 case NAN_ATTRIBUTE_RANGING_EGRESS_LIMIT
:
3741 if (nla_len(iter
) != sizeof(uint32
)) {
3745 cmd_data
->egress_limit
= nla_get_u32(iter
);
3747 case NAN_ATTRIBUTE_RANGING_INDICATION
:
3748 if (nla_len(iter
) != sizeof(uint32
)) {
3752 cmd_data
->ranging_indication
= nla_get_u32(iter
);
3754 /* Nan accept policy: Per service basis policy
3755 * Based on this policy(ALL/NONE), responder side
3756 * will send ACCEPT/REJECT
3758 case NAN_ATTRIBUTE_SVC_RESPONDER_POLICY
:
3759 if (nla_len(iter
) != sizeof(uint8
)) {
3763 cmd_data
->service_responder_policy
= nla_get_u8(iter
);
3766 WL_ERR(("Unknown type, %d\n", attr_type
));
3772 /* We need to call set_config_handler b/f calling start enable TBD */
3778 wl_cfgvendor_nan_parse_args(struct wiphy
*wiphy
, const void *buf
,
3779 int len
, nan_config_cmd_data_t
*cmd_data
, uint32
*nan_attr_mask
)
3784 const struct nlattr
*iter
;
3785 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
3787 u8 sid_beacon
= 0, sub_sid_beacon
= 0;
3791 nla_for_each_attr(iter
, buf
, len
, rem
) {
3792 attr_type
= nla_type(iter
);
3793 WL_TRACE(("attr: %s (%u)\n", nan_attr_to_str(attr_type
), attr_type
));
3795 switch (attr_type
) {
3796 /* NAN Enable request attributes */
3797 case NAN_ATTRIBUTE_2G_SUPPORT
:{
3798 if (nla_len(iter
) != sizeof(uint8
)) {
3802 cmd_data
->support_2g
= nla_get_u8(iter
);
3803 *nan_attr_mask
|= NAN_ATTR_SUPPORT_2G_CONFIG
;
3806 case NAN_ATTRIBUTE_5G_SUPPORT
:{
3807 if (nla_len(iter
) != sizeof(uint8
)) {
3811 cmd_data
->support_5g
= nla_get_u8(iter
);
3812 *nan_attr_mask
|= NAN_ATTR_SUPPORT_5G_CONFIG
;
3815 case NAN_ATTRIBUTE_CLUSTER_LOW
: {
3816 if (nla_len(iter
) != sizeof(uint16
)) {
3820 cmd_data
->clus_id
.octet
[5] = nla_get_u16(iter
);
3823 case NAN_ATTRIBUTE_CLUSTER_HIGH
: {
3824 if (nla_len(iter
) != sizeof(uint16
)) {
3828 cmd_data
->clus_id
.octet
[4] = nla_get_u16(iter
);
3831 case NAN_ATTRIBUTE_SID_BEACON
: {
3832 if (nla_len(iter
) != sizeof(uint8
)) {
3836 sid_beacon
= nla_get_u8(iter
);
3837 cmd_data
->sid_beacon
.sid_enable
= (sid_beacon
& 0x01);
3838 if (cmd_data
->sid_beacon
.sid_enable
) {
3839 cmd_data
->sid_beacon
.sid_count
= (sid_beacon
>> 1);
3840 *nan_attr_mask
|= NAN_ATTR_SID_BEACON_CONFIG
;
3844 case NAN_ATTRIBUTE_SUB_SID_BEACON
: {
3845 if (nla_len(iter
) != sizeof(uint8
)) {
3849 sub_sid_beacon
= nla_get_u8(iter
);
3850 cmd_data
->sid_beacon
.sub_sid_enable
= (sub_sid_beacon
& 0x01);
3851 if (cmd_data
->sid_beacon
.sub_sid_enable
) {
3852 cmd_data
->sid_beacon
.sub_sid_count
= (sub_sid_beacon
>> 1);
3853 *nan_attr_mask
|= NAN_ATTR_SUB_SID_BEACON_CONFIG
;
3857 case NAN_ATTRIBUTE_SYNC_DISC_2G_BEACON
:
3858 if (nla_len(iter
) != sizeof(uint8
)) {
3862 cmd_data
->beacon_2g_val
= nla_get_u8(iter
);
3863 *nan_attr_mask
|= NAN_ATTR_SYNC_DISC_2G_BEACON_CONFIG
;
3865 case NAN_ATTRIBUTE_SYNC_DISC_5G_BEACON
:
3866 if (nla_len(iter
) != sizeof(uint8
)) {
3870 cmd_data
->beacon_5g_val
= nla_get_u8(iter
);
3871 *nan_attr_mask
|= NAN_ATTR_SYNC_DISC_5G_BEACON_CONFIG
;
3873 case NAN_ATTRIBUTE_SDF_2G_SUPPORT
:
3874 if (nla_len(iter
) != sizeof(uint8
)) {
3878 cmd_data
->sdf_2g_val
= nla_get_u8(iter
);
3879 *nan_attr_mask
|= NAN_ATTR_SDF_2G_SUPPORT_CONFIG
;
3881 case NAN_ATTRIBUTE_SDF_5G_SUPPORT
:
3882 if (nla_len(iter
) != sizeof(uint8
)) {
3886 cmd_data
->sdf_5g_val
= nla_get_u8(iter
);
3887 *nan_attr_mask
|= NAN_ATTR_SDF_5G_SUPPORT_CONFIG
;
3889 case NAN_ATTRIBUTE_HOP_COUNT_LIMIT
:
3890 if (nla_len(iter
) != sizeof(uint8
)) {
3894 cmd_data
->hop_count_limit
= nla_get_u8(iter
);
3895 *nan_attr_mask
|= NAN_ATTR_HOP_COUNT_LIMIT_CONFIG
;
3897 case NAN_ATTRIBUTE_RANDOM_TIME
:
3898 if (nla_len(iter
) != sizeof(uint8
)) {
3902 cmd_data
->metrics
.random_factor
= nla_get_u8(iter
);
3903 *nan_attr_mask
|= NAN_ATTR_RAND_FACTOR_CONFIG
;
3905 case NAN_ATTRIBUTE_MASTER_PREF
:
3906 if (nla_len(iter
) != sizeof(uint8
)) {
3910 cmd_data
->metrics
.master_pref
= nla_get_u8(iter
);
3912 case NAN_ATTRIBUTE_OUI
:
3913 if (nla_len(iter
) != sizeof(uint32
)) {
3917 cmd_data
->nan_oui
= nla_get_u32(iter
);
3918 *nan_attr_mask
|= NAN_ATTR_OUI_CONFIG
;
3919 WL_TRACE(("nan_oui=%d\n", cmd_data
->nan_oui
));
3921 case NAN_ATTRIBUTE_WARMUP_TIME
:
3922 if (nla_len(iter
) != sizeof(uint16
)) {
3926 cmd_data
->warmup_time
= nla_get_u16(iter
);
3928 case NAN_ATTRIBUTE_AMBTT
:
3929 case NAN_ATTRIBUTE_MASTER_RANK
:
3930 WL_DBG(("Unhandled attribute, %d\n", attr_type
));
3932 case NAN_ATTRIBUTE_CHANNEL
: {
3933 if (nla_len(iter
) != sizeof(uint32
)) {
3937 /* take the default channel start_factor frequency */
3938 chan
= wf_mhz2channel((uint
)nla_get_u32(iter
), 0);
3939 if (chan
<= CH_MAX_2G_CHANNEL
) {
3940 cmd_data
->chanspec
[0] = wf_channel2chspec(chan
, WL_CHANSPEC_BW_20
);
3942 cmd_data
->chanspec
[0] = wf_channel2chspec(chan
, WL_CHANSPEC_BW_80
);
3944 if (cmd_data
->chanspec
[0] == 0) {
3945 WL_ERR(("Channel is not valid \n"));
3949 WL_TRACE(("valid chanspec, chanspec = 0x%04x \n",
3950 cmd_data
->chanspec
[0]));
3953 case NAN_ATTRIBUTE_24G_CHANNEL
: {
3954 if (nla_len(iter
) != sizeof(uint32
)) {
3958 /* take the default channel start_factor frequency */
3959 chan
= wf_mhz2channel((uint
)nla_get_u32(iter
), 0);
3961 cmd_data
->chanspec
[1] = wf_channel2chspec(chan
, WL_CHANSPEC_BW_20
);
3962 if (cmd_data
->chanspec
[1] == 0) {
3963 WL_ERR((" 2.4GHz Channel is not valid \n"));
3967 *nan_attr_mask
|= NAN_ATTR_2G_CHAN_CONFIG
;
3968 WL_TRACE(("valid 2.4GHz chanspec, chanspec = 0x%04x \n",
3969 cmd_data
->chanspec
[1]));
3972 case NAN_ATTRIBUTE_5G_CHANNEL
: {
3973 if (nla_len(iter
) != sizeof(uint32
)) {
3977 /* take the default channel start_factor frequency */
3978 chan
= wf_mhz2channel((uint
)nla_get_u32(iter
), 0);
3980 cmd_data
->chanspec
[2] = wf_channel2chspec(chan
, WL_CHANSPEC_BW_20
);
3981 if (cmd_data
->chanspec
[2] == 0) {
3982 WL_ERR((" 5GHz Channel is not valid \n"));
3986 *nan_attr_mask
|= NAN_ATTR_5G_CHAN_CONFIG
;
3987 WL_TRACE(("valid 5GHz chanspec, chanspec = 0x%04x \n",
3988 cmd_data
->chanspec
[2]));
3991 case NAN_ATTRIBUTE_CONF_CLUSTER_VAL
:
3992 if (nla_len(iter
) != sizeof(uint8
)) {
3996 cmd_data
->config_cluster_val
= nla_get_u8(iter
);
3997 *nan_attr_mask
|= NAN_ATTR_CLUSTER_VAL_CONFIG
;
3999 case NAN_ATTRIBUTE_DWELL_TIME
:
4000 if (nla_len(iter
) != sizeof(uint8
)) {
4004 cmd_data
->dwell_time
[0] = nla_get_u8(iter
);
4005 *nan_attr_mask
|= NAN_ATTR_2G_DWELL_TIME_CONFIG
;
4007 case NAN_ATTRIBUTE_SCAN_PERIOD
:
4008 if (nla_len(iter
) != sizeof(uint16
)) {
4012 cmd_data
->scan_period
[0] = nla_get_u16(iter
);
4013 *nan_attr_mask
|= NAN_ATTR_2G_SCAN_PERIOD_CONFIG
;
4015 case NAN_ATTRIBUTE_DWELL_TIME_5G
:
4016 if (nla_len(iter
) != sizeof(uint8
)) {
4020 cmd_data
->dwell_time
[1] = nla_get_u8(iter
);
4021 *nan_attr_mask
|= NAN_ATTR_5G_DWELL_TIME_CONFIG
;
4023 case NAN_ATTRIBUTE_SCAN_PERIOD_5G
:
4024 if (nla_len(iter
) != sizeof(uint16
)) {
4028 cmd_data
->scan_period
[1] = nla_get_u16(iter
);
4029 *nan_attr_mask
|= NAN_ATTR_5G_SCAN_PERIOD_CONFIG
;
4031 case NAN_ATTRIBUTE_AVAIL_BIT_MAP
:
4032 if (nla_len(iter
) != sizeof(uint32
)) {
4036 cmd_data
->bmap
= nla_get_u32(iter
);
4038 case NAN_ATTRIBUTE_ENTRY_CONTROL
:
4039 if (nla_len(iter
) != sizeof(uint8
)) {
4043 cmd_data
->avail_params
.duration
= nla_get_u8(iter
);
4045 case NAN_ATTRIBUTE_RSSI_CLOSE
:
4046 if (nla_len(iter
) != sizeof(uint8
)) {
4050 cmd_data
->rssi_attr
.rssi_close_2dot4g_val
= nla_get_s8(iter
);
4051 *nan_attr_mask
|= NAN_ATTR_RSSI_CLOSE_CONFIG
;
4053 case NAN_ATTRIBUTE_RSSI_MIDDLE
:
4054 if (nla_len(iter
) != sizeof(uint8
)) {
4058 cmd_data
->rssi_attr
.rssi_middle_2dot4g_val
= nla_get_s8(iter
);
4059 *nan_attr_mask
|= NAN_ATTR_RSSI_MIDDLE_2G_CONFIG
;
4061 case NAN_ATTRIBUTE_RSSI_PROXIMITY
:
4062 if (nla_len(iter
) != sizeof(uint8
)) {
4066 cmd_data
->rssi_attr
.rssi_proximity_2dot4g_val
= nla_get_s8(iter
);
4067 *nan_attr_mask
|= NAN_ATTR_RSSI_PROXIMITY_2G_CONFIG
;
4069 case NAN_ATTRIBUTE_RSSI_CLOSE_5G
:
4070 if (nla_len(iter
) != sizeof(uint8
)) {
4074 cmd_data
->rssi_attr
.rssi_close_5g_val
= nla_get_s8(iter
);
4075 *nan_attr_mask
|= NAN_ATTR_RSSI_CLOSE_5G_CONFIG
;
4077 case NAN_ATTRIBUTE_RSSI_MIDDLE_5G
:
4078 if (nla_len(iter
) != sizeof(uint8
)) {
4082 cmd_data
->rssi_attr
.rssi_middle_5g_val
= nla_get_s8(iter
);
4083 *nan_attr_mask
|= NAN_ATTR_RSSI_MIDDLE_5G_CONFIG
;
4085 case NAN_ATTRIBUTE_RSSI_PROXIMITY_5G
:
4086 if (nla_len(iter
) != sizeof(uint8
)) {
4090 cmd_data
->rssi_attr
.rssi_proximity_5g_val
= nla_get_s8(iter
);
4091 *nan_attr_mask
|= NAN_ATTR_RSSI_PROXIMITY_5G_CONFIG
;
4093 case NAN_ATTRIBUTE_RSSI_WINDOW_SIZE
:
4094 if (nla_len(iter
) != sizeof(uint8
)) {
4098 cmd_data
->rssi_attr
.rssi_window_size
= nla_get_u8(iter
);
4099 *nan_attr_mask
|= NAN_ATTR_RSSI_WINDOW_SIZE_CONFIG
;
4101 case NAN_ATTRIBUTE_CIPHER_SUITE_TYPE
:
4102 if (nla_len(iter
) != sizeof(uint8
)) {
4106 cmd_data
->csid
= nla_get_u8(iter
);
4107 WL_TRACE(("CSID = %u\n", cmd_data
->csid
));
4109 case NAN_ATTRIBUTE_SCID_LEN
:
4110 if (nla_len(iter
) != sizeof(uint32
)) {
4114 if (cmd_data
->scid
.dlen
) {
4115 WL_ERR(("trying to overwrite:%d\n", attr_type
));
4119 cmd_data
->scid
.dlen
= nla_get_u32(iter
);
4120 if (cmd_data
->scid
.dlen
> MAX_SCID_LEN
) {
4122 WL_ERR(("Not allowed beyond %d\n", MAX_SCID_LEN
));
4125 WL_TRACE(("valid scid length = %u\n", cmd_data
->scid
.dlen
));
4127 case NAN_ATTRIBUTE_SCID
:
4128 if (!cmd_data
->scid
.dlen
|| (nla_len(iter
) != cmd_data
->scid
.dlen
)) {
4129 WL_ERR(("wrong scid len:%d,%d\n", cmd_data
->scid
.dlen
,
4134 if (cmd_data
->scid
.data
) {
4135 WL_ERR(("trying to overwrite:%d\n", attr_type
));
4139 cmd_data
->scid
.data
= MALLOCZ(cfg
->osh
, cmd_data
->scid
.dlen
);
4140 if (cmd_data
->scid
.data
== NULL
) {
4141 WL_ERR(("failed to allocate scid, len=%d\n",
4142 cmd_data
->scid
.dlen
));
4146 memcpy(cmd_data
->scid
.data
, nla_data(iter
), cmd_data
->scid
.dlen
);
4148 case NAN_ATTRIBUTE_2G_AWAKE_DW
:
4149 if (nla_len(iter
) != sizeof(uint32
)) {
4153 if (nla_get_u32(iter
) > NAN_MAX_AWAKE_DW_INTERVAL
) {
4154 WL_ERR(("%s: Invalid/Out of bound value = %u\n",
4155 __FUNCTION__
, nla_get_u32(iter
)));
4159 if (nla_get_u32(iter
)) {
4160 cmd_data
->awake_dws
.dw_interval_2g
=
4161 1 << (nla_get_u32(iter
)-1);
4163 *nan_attr_mask
|= NAN_ATTR_2G_DW_CONFIG
;
4165 case NAN_ATTRIBUTE_5G_AWAKE_DW
:
4166 if (nla_len(iter
) != sizeof(uint32
)) {
4170 if (nla_get_u32(iter
) > NAN_MAX_AWAKE_DW_INTERVAL
) {
4171 WL_ERR(("%s: Invalid/Out of bound value = %u\n",
4172 __FUNCTION__
, nla_get_u32(iter
)));
4176 if (nla_get_u32(iter
)) {
4177 cmd_data
->awake_dws
.dw_interval_5g
=
4178 1 << (nla_get_u32(iter
)-1);
4180 *nan_attr_mask
|= NAN_ATTR_5G_DW_CONFIG
;
4182 case NAN_ATTRIBUTE_DISC_IND_CFG
:
4183 if (nla_len(iter
) != sizeof(uint8
)) {
4187 cmd_data
->disc_ind_cfg
= nla_get_u8(iter
);
4189 case NAN_ATTRIBUTE_MAC_ADDR
:
4190 if (nla_len(iter
) != ETHER_ADDR_LEN
) {
4194 memcpy((char*)&cmd_data
->mac_addr
, (char*)nla_data(iter
),
4197 case NAN_ATTRIBUTE_RANDOMIZATION_INTERVAL
:
4198 if (nla_len(iter
) != sizeof(uint32
)) {
4202 cmd_data
->nmi_rand_intvl
= nla_get_u8(iter
);
4203 if (cmd_data
->nmi_rand_intvl
> 0) {
4204 cfg
->nancfg
.mac_rand
= true;
4206 cfg
->nancfg
.mac_rand
= false;
4210 WL_ERR(("%s: Unknown type, %d\n", __FUNCTION__
, attr_type
));
4217 /* We need to call set_config_handler b/f calling start enable TBD */
4220 WL_ERR(("%s: Failed to parse attribute %d ret %d",
4221 __FUNCTION__
, attr_type
, ret
));
4228 wl_cfgvendor_nan_dp_estb_event_data_filler(struct sk_buff
*msg
,
4229 nan_event_data_t
*event_data
) {
4231 ret
= nla_put_u32(msg
, NAN_ATTRIBUTE_NDP_ID
, event_data
->ndp_id
);
4232 if (unlikely(ret
)) {
4233 WL_ERR(("Failed to put NDP ID, ret=%d\n", ret
));
4237 * NDI mac address of the peer
4238 * (required to derive target ipv6 address)
4240 ret
= nla_put(msg
, NAN_ATTRIBUTE_PEER_NDI_MAC_ADDR
, ETH_ALEN
,
4241 event_data
->responder_ndi
.octet
);
4242 if (unlikely(ret
)) {
4243 WL_ERR(("Failed to put resp ndi, ret=%d\n", ret
));
4246 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_RSP_CODE
, event_data
->status
);
4247 if (unlikely(ret
)) {
4248 WL_ERR(("Failed to put response code, ret=%d\n", ret
));
4251 if (event_data
->svc_info
.dlen
&& event_data
->svc_info
.data
) {
4252 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN
,
4253 event_data
->svc_info
.dlen
);
4254 if (unlikely(ret
)) {
4255 WL_ERR(("Failed to put svc info len, ret=%d\n", ret
));
4258 ret
= nla_put(msg
, NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO
,
4259 event_data
->svc_info
.dlen
, event_data
->svc_info
.data
);
4260 if (unlikely(ret
)) {
4261 WL_ERR(("Failed to put svc info, ret=%d\n", ret
));
4270 wl_cfgvendor_nan_dp_ind_event_data_filler(struct sk_buff
*msg
,
4271 nan_event_data_t
*event_data
) {
4274 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_PUBLISH_ID
,
4275 event_data
->pub_id
);
4276 if (unlikely(ret
)) {
4277 WL_ERR(("Failed to put pub ID, ret=%d\n", ret
));
4280 ret
= nla_put_u32(msg
, NAN_ATTRIBUTE_NDP_ID
, event_data
->ndp_id
);
4281 if (unlikely(ret
)) {
4282 WL_ERR(("Failed to put NDP ID, ret=%d\n", ret
));
4285 /* Discovery MAC addr of the peer/initiator */
4286 ret
= nla_put(msg
, NAN_ATTRIBUTE_MAC_ADDR
, ETH_ALEN
,
4287 event_data
->remote_nmi
.octet
);
4288 if (unlikely(ret
)) {
4289 WL_ERR(("Failed to put remote NMI, ret=%d\n", ret
));
4292 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_SECURITY
, event_data
->security
);
4293 if (unlikely(ret
)) {
4294 WL_ERR(("Failed to put security, ret=%d\n", ret
));
4297 if (event_data
->svc_info
.dlen
&& event_data
->svc_info
.data
) {
4298 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN
,
4299 event_data
->svc_info
.dlen
);
4300 if (unlikely(ret
)) {
4301 WL_ERR(("Failed to put svc info len, ret=%d\n", ret
));
4304 ret
= nla_put(msg
, NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO
,
4305 event_data
->svc_info
.dlen
, event_data
->svc_info
.data
);
4306 if (unlikely(ret
)) {
4307 WL_ERR(("Failed to put svc info, ret=%d\n", ret
));
4317 wl_cfgvendor_nan_tx_followup_ind_event_data_filler(struct sk_buff
*msg
,
4318 nan_event_data_t
*event_data
) {
4320 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_TRANSAC_ID
, event_data
->token
);
4321 if (unlikely(ret
)) {
4322 WL_ERR(("Failed to put transaction id, ret=%d\n", ret
));
4325 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_HANDLE
, event_data
->local_inst_id
);
4326 if (unlikely(ret
)) {
4327 WL_ERR(("Failed to put handle, ret=%d\n", ret
));
4330 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_STATUS
, event_data
->status
);
4331 if (unlikely(ret
)) {
4332 WL_ERR(("Failed to put nan status, ret=%d\n", ret
));
4335 if (event_data
->status
== NAN_STATUS_SUCCESS
) {
4336 ret
= nla_put(msg
, NAN_ATTRIBUTE_REASON
,
4337 strlen("NAN_STATUS_SUCCESS"), event_data
->nan_reason
);
4338 if (unlikely(ret
)) {
4339 WL_ERR(("Failed to put nan reason, ret=%d\n", ret
));
4343 ret
= nla_put(msg
, NAN_ATTRIBUTE_REASON
,
4344 strlen("NAN_STATUS_NO_OTA_ACK"), event_data
->nan_reason
);
4345 if (unlikely(ret
)) {
4346 WL_ERR(("Failed to put nan reason, ret=%d\n", ret
));
4355 wl_cfgvendor_nan_svc_terminate_event_filler(struct sk_buff
*msg
,
4356 struct bcm_cfg80211
*cfg
, int event_id
, nan_event_data_t
*event_data
) {
4358 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_HANDLE
, event_data
->local_inst_id
);
4359 if (unlikely(ret
)) {
4360 WL_ERR(("Failed to put handle, ret=%d\n", ret
));
4364 if (event_id
== GOOGLE_NAN_EVENT_SUBSCRIBE_TERMINATED
) {
4365 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_SUBSCRIBE_ID
,
4366 event_data
->local_inst_id
);
4367 if (unlikely(ret
)) {
4368 WL_ERR(("Failed to put local inst id, ret=%d\n", ret
));
4372 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_PUBLISH_ID
,
4373 event_data
->local_inst_id
);
4374 if (unlikely(ret
)) {
4375 WL_ERR(("Failed to put local inst id, ret=%d\n", ret
));
4379 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_STATUS
, event_data
->status
);
4380 if (unlikely(ret
)) {
4381 WL_ERR(("Failed to put status, ret=%d\n", ret
));
4384 if (event_data
->status
== NAN_STATUS_SUCCESS
) {
4385 ret
= nla_put(msg
, NAN_ATTRIBUTE_REASON
,
4386 strlen("NAN_STATUS_SUCCESS"), event_data
->nan_reason
);
4387 if (unlikely(ret
)) {
4388 WL_ERR(("Failed to put nan reason, ret=%d\n", ret
));
4392 ret
= nla_put(msg
, NAN_ATTRIBUTE_REASON
,
4393 strlen("NAN_STATUS_INTERNAL_FAILURE"), event_data
->nan_reason
);
4394 if (unlikely(ret
)) {
4395 WL_ERR(("Failed to put nan reason, ret=%d\n", ret
));
4400 ret
= wl_cfgnan_remove_inst_id(cfg
, event_data
->local_inst_id
);
4402 WL_ERR(("failed to free svc instance-id[%d], ret=%d, event_id = %d\n",
4403 event_data
->local_inst_id
, ret
, event_id
));
4411 wl_cfgvendor_nan_opt_params_filler(struct sk_buff
*msg
,
4412 nan_event_data_t
*event_data
) {
4414 /* service specific info data */
4415 if (event_data
->svc_info
.dlen
&& event_data
->svc_info
.data
) {
4416 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN
,
4417 event_data
->svc_info
.dlen
);
4418 if (unlikely(ret
)) {
4419 WL_ERR(("Failed to put svc info len, ret=%d\n", ret
));
4422 ret
= nla_put(msg
, NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO
,
4423 event_data
->svc_info
.dlen
, event_data
->svc_info
.data
);
4424 if (unlikely(ret
)) {
4425 WL_ERR(("Failed to put svc info, ret=%d\n", ret
));
4428 WL_TRACE(("svc info len = %d\n", event_data
->svc_info
.dlen
));
4431 /* sdea service specific info data */
4432 if (event_data
->sde_svc_info
.dlen
&& event_data
->sde_svc_info
.data
) {
4433 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN
,
4434 event_data
->sde_svc_info
.dlen
);
4435 if (unlikely(ret
)) {
4436 WL_ERR(("Failed to put sdea svc info len, ret=%d\n", ret
));
4439 ret
= nla_put(msg
, NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO
,
4440 event_data
->sde_svc_info
.dlen
,
4441 event_data
->sde_svc_info
.data
);
4442 if (unlikely(ret
)) {
4443 WL_ERR(("Failed to put sdea svc info, ret=%d\n", ret
));
4446 WL_TRACE(("sdea svc info len = %d\n", event_data
->sde_svc_info
.dlen
));
4448 /* service control discovery range limit */
4451 /* service control binding bitmap */
4458 wl_cfgvendor_nan_tx_followup_event_filler(struct sk_buff
*msg
,
4459 nan_event_data_t
*event_data
) {
4461 /* In followup pkt, instance id and requestor instance id are configured
4462 * from the transmitter perspective. As the event is processed with the
4463 * role of receiver, the local handle should use requestor instance
4466 WL_TRACE(("handle=%d\n", event_data
->requestor_id
));
4467 WL_TRACE(("inst id (local id)=%d\n", event_data
->local_inst_id
));
4468 WL_TRACE(("peer id (remote id)=%d\n", event_data
->requestor_id
));
4469 WL_TRACE(("peer mac addr=" MACDBG
"\n",
4470 MAC2STRDBG(event_data
->remote_nmi
.octet
)));
4471 WL_TRACE(("peer rssi: %d\n", event_data
->fup_rssi
));
4472 WL_TRACE(("attribute no: %d\n", event_data
->attr_num
));
4473 WL_TRACE(("attribute len: %d\n", event_data
->attr_list_len
));
4475 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_HANDLE
, event_data
->requestor_id
);
4476 if (unlikely(ret
)) {
4477 WL_ERR(("Failed to put handle, ret=%d\n", ret
));
4480 ret
= nla_put_u32(msg
, NAN_ATTRIBUTE_INST_ID
, event_data
->local_inst_id
);
4481 if (unlikely(ret
)) {
4482 WL_ERR(("Failed to put local inst id, ret=%d\n", ret
));
4485 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_PEER_ID
, event_data
->requestor_id
);
4486 if (unlikely(ret
)) {
4487 WL_ERR(("Failed to put requestor inst id, ret=%d\n", ret
));
4490 ret
= nla_put(msg
, NAN_ATTRIBUTE_MAC_ADDR
, ETHER_ADDR_LEN
,
4491 event_data
->remote_nmi
.octet
);
4492 if (unlikely(ret
)) {
4493 WL_ERR(("Failed to put remote nmi, ret=%d\n", ret
));
4496 ret
= nla_put_s8(msg
, NAN_ATTRIBUTE_RSSI_PROXIMITY
,
4497 event_data
->fup_rssi
);
4498 if (unlikely(ret
)) {
4499 WL_ERR(("Failed to put fup rssi, ret=%d\n", ret
));
4507 wl_cfgvendor_nan_sub_match_event_filler(struct sk_buff
*msg
,
4508 nan_event_data_t
*event_data
) {
4510 WL_TRACE(("handle (sub_id)=%d\n", event_data
->sub_id
));
4511 WL_TRACE(("pub id=%d\n", event_data
->pub_id
));
4512 WL_TRACE(("sub id=%d\n", event_data
->sub_id
));
4513 WL_TRACE(("pub mac addr=" MACDBG
"\n",
4514 MAC2STRDBG(event_data
->remote_nmi
.octet
)));
4515 WL_TRACE(("attr no: %d\n", event_data
->attr_num
));
4516 WL_TRACE(("attr len: %d\n", event_data
->attr_list_len
));
4518 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_HANDLE
, event_data
->sub_id
);
4519 if (unlikely(ret
)) {
4520 WL_ERR(("Failed to put handle, ret=%d\n", ret
));
4523 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_PUBLISH_ID
, event_data
->pub_id
);
4524 if (unlikely(ret
)) {
4525 WL_ERR(("Failed to put pub id, ret=%d\n", ret
));
4528 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_SUBSCRIBE_ID
, event_data
->sub_id
);
4529 if (unlikely(ret
)) {
4530 WL_ERR(("Failed to put Sub Id, ret=%d\n", ret
));
4533 ret
= nla_put(msg
, NAN_ATTRIBUTE_MAC_ADDR
, ETHER_ADDR_LEN
,
4534 event_data
->remote_nmi
.octet
);
4535 if (unlikely(ret
)) {
4536 WL_ERR(("Failed to put remote NMI, ret=%d\n", ret
));
4539 if (event_data
->publish_rssi
) {
4540 event_data
->publish_rssi
= -event_data
->publish_rssi
;
4541 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_RSSI_PROXIMITY
,
4542 event_data
->publish_rssi
);
4543 if (unlikely(ret
)) {
4544 WL_ERR(("Failed to put publish rssi, ret=%d\n", ret
));
4548 if (event_data
->ranging_result_present
) {
4549 ret
= nla_put_u32(msg
, NAN_ATTRIBUTE_RANGING_INDICATION
,
4550 event_data
->ranging_ind
);
4551 if (unlikely(ret
)) {
4552 WL_ERR(("Failed to put ranging ind, ret=%d\n", ret
));
4555 ret
= nla_put_u32(msg
, NAN_ATTRIBUTE_RANGING_RESULT
,
4556 event_data
->range_measurement_cm
);
4557 if (unlikely(ret
)) {
4558 WL_ERR(("Failed to put range measurement cm, ret=%d\n",
4564 * handling optional service control, service response filter
4566 if (event_data
->tx_match_filter
.dlen
&& event_data
->tx_match_filter
.data
) {
4567 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_TX_MATCH_FILTER_LEN
,
4568 event_data
->tx_match_filter
.dlen
);
4569 if (unlikely(ret
)) {
4570 WL_ERR(("Failed to put tx match filter len, ret=%d\n",
4574 ret
= nla_put(msg
, NAN_ATTRIBUTE_TX_MATCH_FILTER
,
4575 event_data
->tx_match_filter
.dlen
,
4576 event_data
->tx_match_filter
.data
);
4577 if (unlikely(ret
)) {
4578 WL_ERR(("Failed to put tx match filter data, ret=%d\n",
4582 WL_TRACE(("tx matching filter (%d):\n",
4583 event_data
->tx_match_filter
.dlen
));
4591 wl_cfgvendor_nan_de_event_filler(struct sk_buff
*msg
, nan_event_data_t
*event_data
)
4594 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_ENABLE_STATUS
, event_data
->enabled
);
4595 if (unlikely(ret
)) {
4596 WL_ERR(("Failed to put event_data->enabled, ret=%d\n", ret
));
4599 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_DE_EVENT_TYPE
,
4600 event_data
->nan_de_evt_type
);
4601 if (unlikely(ret
)) {
4602 WL_ERR(("Failed to put nan_de_evt_type, ret=%d\n", ret
));
4605 ret
= nla_put(msg
, NAN_ATTRIBUTE_CLUSTER_ID
, ETH_ALEN
,
4606 event_data
->clus_id
.octet
);
4607 if (unlikely(ret
)) {
4608 WL_ERR(("Failed to put clust id, ret=%d\n", ret
));
4611 /* OOB tests requires local nmi */
4612 ret
= nla_put(msg
, NAN_ATTRIBUTE_MAC_ADDR
, ETH_ALEN
,
4613 event_data
->local_nmi
.octet
);
4614 if (unlikely(ret
)) {
4615 WL_ERR(("Failed to put NMI, ret=%d\n", ret
));
4623 wl_cfgvendor_send_nan_event(struct wiphy
*wiphy
, struct net_device
*dev
,
4624 int event_id
, nan_event_data_t
*event_data
)
4627 int buf_len
= NAN_EVENT_BUFFER_SIZE_LARGE
;
4628 u16 kflags
= in_atomic() ? GFP_ATOMIC
: GFP_KERNEL
;
4630 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
4631 struct sk_buff
*msg
;
4635 /* Allocate the skb for vendor event */
4636 #if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
4637 LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
4638 msg
= cfg80211_vendor_event_alloc(wiphy
, ndev_to_wdev(dev
), buf_len
, event_id
, kflags
);
4640 msg
= cfg80211_vendor_event_alloc(wiphy
, buf_len
, event_id
, kflags
);
4641 #endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
4642 /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */
4645 WL_ERR(("%s: fail to allocate skb for vendor event\n", __FUNCTION__
));
4650 case GOOGLE_NAN_EVENT_DE_EVENT
: {
4651 WL_INFORM_MEM(("[NAN] GOOGLE_NAN_DE_EVENT cluster id=" MACDBG
"nmi= " MACDBG
"\n",
4652 MAC2STRDBG(event_data
->clus_id
.octet
),
4653 MAC2STRDBG(event_data
->local_nmi
.octet
)));
4654 ret
= wl_cfgvendor_nan_de_event_filler(msg
, event_data
);
4655 if (unlikely(ret
)) {
4656 WL_ERR(("Failed to fill de event data, ret=%d\n", ret
));
4661 case GOOGLE_NAN_EVENT_SUBSCRIBE_MATCH
:
4662 case GOOGLE_NAN_EVENT_FOLLOWUP
: {
4663 if (event_id
== GOOGLE_NAN_EVENT_SUBSCRIBE_MATCH
) {
4664 WL_DBG(("GOOGLE_NAN_EVENT_SUBSCRIBE_MATCH\n"));
4665 ret
= wl_cfgvendor_nan_sub_match_event_filler(msg
, event_data
);
4666 if (unlikely(ret
)) {
4667 WL_ERR(("Failed to fill sub match event data, ret=%d\n", ret
));
4670 } else if (event_id
== GOOGLE_NAN_EVENT_FOLLOWUP
) {
4671 WL_DBG(("GOOGLE_NAN_EVENT_FOLLOWUP\n"));
4672 ret
= wl_cfgvendor_nan_tx_followup_event_filler(msg
, event_data
);
4673 if (unlikely(ret
)) {
4674 WL_ERR(("Failed to fill sub match event data, ret=%d\n", ret
));
4678 ret
= wl_cfgvendor_nan_opt_params_filler(msg
, event_data
);
4679 if (unlikely(ret
)) {
4680 WL_ERR(("Failed to fill sub match event data, ret=%d\n", ret
));
4686 case GOOGLE_NAN_EVENT_DISABLED
: {
4687 WL_INFORM_MEM(("[NAN] GOOGLE_NAN_EVENT_DISABLED\n"));
4688 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_HANDLE
, 0);
4689 if (unlikely(ret
)) {
4690 WL_ERR(("Failed to put handle, ret=%d\n", ret
));
4693 ret
= nla_put_u16(msg
, NAN_ATTRIBUTE_STATUS
, event_data
->status
);
4694 if (unlikely(ret
)) {
4695 WL_ERR(("Failed to put status, ret=%d\n", ret
));
4698 ret
= nla_put(msg
, NAN_ATTRIBUTE_REASON
,
4699 strlen("NAN_STATUS_SUCCESS"), event_data
->nan_reason
);
4700 if (unlikely(ret
)) {
4701 WL_ERR(("Failed to put reason code, ret=%d\n", ret
));
4707 case GOOGLE_NAN_EVENT_SUBSCRIBE_TERMINATED
:
4708 case GOOGLE_NAN_EVENT_PUBLISH_TERMINATED
: {
4709 WL_DBG(("GOOGLE_NAN_SVC_TERMINATED, %d\n", event_id
));
4710 ret
= wl_cfgvendor_nan_svc_terminate_event_filler(msg
, cfg
, event_id
, event_data
);
4711 if (unlikely(ret
)) {
4712 WL_ERR(("Failed to fill svc terminate event data, ret=%d\n", ret
));
4718 case GOOGLE_NAN_EVENT_TRANSMIT_FOLLOWUP_IND
: {
4719 WL_DBG(("GOOGLE_NAN_EVENT_TRANSMIT_FOLLOWUP_IND %d\n",
4720 GOOGLE_NAN_EVENT_TRANSMIT_FOLLOWUP_IND
));
4721 ret
= wl_cfgvendor_nan_tx_followup_ind_event_data_filler(msg
, event_data
);
4722 if (unlikely(ret
)) {
4723 WL_ERR(("Failed to fill tx follow up ind event data, ret=%d\n", ret
));
4730 case GOOGLE_NAN_EVENT_DATA_REQUEST
: {
4731 WL_INFORM_MEM(("[NAN] GOOGLE_NAN_EVENT_DATA_REQUEST\n"));
4732 ret
= wl_cfgvendor_nan_dp_ind_event_data_filler(msg
, event_data
);
4733 if (unlikely(ret
)) {
4734 WL_ERR(("Failed to fill dp ind event data, ret=%d\n", ret
));
4740 case GOOGLE_NAN_EVENT_DATA_CONFIRMATION
: {
4741 WL_INFORM_MEM(("[NAN] GOOGLE_NAN_EVENT_DATA_CONFIRMATION\n"));
4743 ret
= wl_cfgvendor_nan_dp_estb_event_data_filler(msg
, event_data
);
4744 if (unlikely(ret
)) {
4745 WL_ERR(("Failed to fill dp estb event data, ret=%d\n", ret
));
4751 case GOOGLE_NAN_EVENT_DATA_END
: {
4752 WL_INFORM_MEM(("[NAN] GOOGLE_NAN_EVENT_DATA_END\n"));
4753 ret
= nla_put_u8(msg
, NAN_ATTRIBUTE_INST_COUNT
, 1);
4754 if (unlikely(ret
)) {
4755 WL_ERR(("Failed to put inst count, ret=%d\n", ret
));
4758 ret
= nla_put_u32(msg
, NAN_ATTRIBUTE_NDP_ID
, event_data
->ndp_id
);
4759 if (unlikely(ret
)) {
4760 WL_ERR(("Failed to put ndp id, ret=%d\n", ret
));
4770 cfg80211_vendor_event(msg
, kflags
);
4775 dev_kfree_skb_any(msg
);
4776 WL_ERR(("Event not implemented or unknown -- Free skb, event_id = %d, ret = %d\n",
4783 wl_cfgvendor_nan_req_subscribe(struct wiphy
*wiphy
,
4784 struct wireless_dev
*wdev
, const void * data
, int len
)
4787 nan_discover_cmd_data_t
*cmd_data
= NULL
;
4788 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
4789 nan_hal_resp_t nan_req_resp
;
4792 /* Blocking Subscribe if NAN is not enable */
4793 if (!cfg
->nan_enable
) {
4794 WL_ERR(("nan is not enabled, subscribe blocked\n"));
4798 cmd_data
= (nan_discover_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
4800 WL_ERR(("%s: memory allocation failed\n", __func__
));
4805 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
4806 ret
= wl_cfgvendor_nan_parse_discover_args(wiphy
, data
, len
, cmd_data
);
4808 WL_ERR(("failed to parse nan disc vendor args, ret = %d\n", ret
));
4812 if (cmd_data
->sub_id
== 0) {
4813 ret
= wl_cfgnan_generate_inst_id(cfg
, &cmd_data
->sub_id
);
4815 WL_ERR(("failed to generate instance-id for subscribe\n"));
4819 cmd_data
->svc_update
= true;
4822 ret
= wl_cfgnan_subscribe_handler(wdev
->netdev
, cfg
, cmd_data
);
4823 if (unlikely(ret
) || unlikely(cmd_data
->status
)) {
4824 WL_ERR(("failed to subscribe error[%d], status = [%d]\n",
4825 ret
, cmd_data
->status
));
4826 wl_cfgnan_remove_inst_id(cfg
, cmd_data
->sub_id
);
4830 WL_DBG(("subscriber instance id=%d\n", cmd_data
->sub_id
));
4832 if (cmd_data
->status
== WL_NAN_E_OK
) {
4833 nan_req_resp
.instance_id
= cmd_data
->sub_id
;
4835 nan_req_resp
.instance_id
= 0;
4838 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_REQUEST_SUBSCRIBE
,
4839 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
4840 wl_cfgvendor_free_disc_cmd_data(cfg
, cmd_data
);
4846 wl_cfgvendor_nan_req_publish(struct wiphy
*wiphy
,
4847 struct wireless_dev
*wdev
, const void * data
, int len
)
4850 nan_discover_cmd_data_t
*cmd_data
= NULL
;
4851 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
4852 nan_hal_resp_t nan_req_resp
;
4855 /* Blocking Publish if NAN is not enable */
4856 if (!cfg
->nan_enable
) {
4857 WL_ERR(("nan is not enabled publish blocked\n"));
4861 cmd_data
= (nan_discover_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
4863 WL_ERR(("%s: memory allocation failed\n", __func__
));
4868 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
4869 ret
= wl_cfgvendor_nan_parse_discover_args(wiphy
, data
, len
, cmd_data
);
4871 WL_ERR(("failed to parse nan disc vendor args, ret = %d\n", ret
));
4875 if (cmd_data
->pub_id
== 0) {
4876 ret
= wl_cfgnan_generate_inst_id(cfg
, &cmd_data
->pub_id
);
4878 WL_ERR(("failed to generate instance-id for publisher\n"));
4882 cmd_data
->svc_update
= true;
4885 ret
= wl_cfgnan_publish_handler(wdev
->netdev
, cfg
, cmd_data
);
4886 if (unlikely(ret
) || unlikely(cmd_data
->status
)) {
4887 WL_ERR(("failed to publish error[%d], status[%d]\n",
4888 ret
, cmd_data
->status
));
4889 wl_cfgnan_remove_inst_id(cfg
, cmd_data
->pub_id
);
4893 WL_DBG(("publisher instance id=%d\n", cmd_data
->pub_id
));
4895 if (cmd_data
->status
== WL_NAN_E_OK
) {
4896 nan_req_resp
.instance_id
= cmd_data
->pub_id
;
4898 nan_req_resp
.instance_id
= 0;
4901 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_REQUEST_PUBLISH
,
4902 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
4903 wl_cfgvendor_free_disc_cmd_data(cfg
, cmd_data
);
4909 wl_cfgvendor_nan_start_handler(struct wiphy
*wiphy
,
4910 struct wireless_dev
*wdev
, const void *data
, int len
)
4913 nan_config_cmd_data_t
*cmd_data
;
4914 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
4915 nan_hal_resp_t nan_req_resp
;
4916 uint32 nan_attr_mask
= 0;
4918 cmd_data
= (nan_config_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
4920 WL_ERR(("%s: memory allocation failed\n", __func__
));
4926 if (cfg
->nan_enable
) {
4927 WL_ERR(("nan is already enabled\n"));
4932 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
4934 cmd_data
->sid_beacon
.sid_enable
= NAN_SID_ENABLE_FLAG_INVALID
; /* Setting to some default */
4935 cmd_data
->sid_beacon
.sid_count
= NAN_SID_BEACON_COUNT_INVALID
; /* Setting to some default */
4937 ret
= wl_cfgvendor_nan_parse_args(wiphy
, data
, len
, cmd_data
, &nan_attr_mask
);
4939 WL_ERR(("failed to parse nan vendor args, ret %d\n", ret
));
4943 ret
= wl_cfgnan_start_handler(wdev
->netdev
, cfg
, cmd_data
, nan_attr_mask
);
4945 WL_ERR(("failed to start nan error[%d]\n", ret
));
4948 /* Initializing Instance Id List */
4949 memset(cfg
->nan_inst_ctrl
, 0, NAN_ID_CTRL_SIZE
* sizeof(nan_svc_inst_t
));
4951 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_ENABLE
,
4952 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
4954 if (cmd_data
->scid
.data
) {
4955 MFREE(cfg
->osh
, cmd_data
->scid
.data
, cmd_data
->scid
.dlen
);
4956 cmd_data
->scid
.dlen
= 0;
4958 MFREE(cfg
->osh
, cmd_data
, sizeof(*cmd_data
));
4965 wl_cfgvendor_nan_stop_handler(struct wiphy
*wiphy
,
4966 struct wireless_dev
*wdev
, const void * data
, int len
)
4969 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
4970 nan_hal_resp_t nan_req_resp
;
4973 if (!cfg
->nan_init_state
) {
4974 WL_ERR(("nan is not initialized/nmi doesnt exists\n"));
4979 if (cfg
->nan_enable
) {
4980 ret
= wl_cfgnan_disable(cfg
, NAN_USER_INITIATED
);
4982 WL_ERR(("failed to disable nan, error[%d]\n", ret
));
4985 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
4987 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_DISABLE
,
4988 &nan_req_resp
, ret
, BCME_OK
);
4994 wl_cfgvendor_nan_config_handler(struct wiphy
*wiphy
,
4995 struct wireless_dev
*wdev
, const void *data
, int len
)
4998 nan_config_cmd_data_t
*cmd_data
;
4999 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5000 nan_hal_resp_t nan_req_resp
;
5001 uint32 nan_attr_mask
= 0;
5003 cmd_data
= MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
5005 WL_ERR(("%s: memory allocation failed\n", __func__
));
5010 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
5012 cmd_data
->avail_params
.duration
= NAN_BAND_INVALID
; /* Setting to some default */
5013 cmd_data
->sid_beacon
.sid_enable
= NAN_SID_ENABLE_FLAG_INVALID
; /* Setting to some default */
5014 cmd_data
->sid_beacon
.sid_count
= NAN_SID_BEACON_COUNT_INVALID
; /* Setting to some default */
5016 ret
= wl_cfgvendor_nan_parse_args(wiphy
, data
, len
, cmd_data
, &nan_attr_mask
);
5018 WL_ERR(("failed to parse nan vendor args, ret = %d\n", ret
));
5022 ret
= wl_cfgnan_config_handler(wdev
->netdev
, cfg
, cmd_data
, nan_attr_mask
);
5024 WL_ERR(("failed in config request, nan error[%d]\n", ret
));
5028 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_CONFIG
,
5029 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
5031 if (cmd_data
->scid
.data
) {
5032 MFREE(cfg
->osh
, cmd_data
->scid
.data
, cmd_data
->scid
.dlen
);
5033 cmd_data
->scid
.dlen
= 0;
5035 MFREE(cfg
->osh
, cmd_data
, sizeof(*cmd_data
));
5042 wl_cfgvendor_nan_cancel_publish(struct wiphy
*wiphy
,
5043 struct wireless_dev
*wdev
, const void * data
, int len
)
5046 nan_discover_cmd_data_t
*cmd_data
= NULL
;
5047 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5048 nan_hal_resp_t nan_req_resp
;
5050 /* Blocking Cancel_Publish if NAN is not enable */
5051 if (!cfg
->nan_enable
) {
5052 WL_ERR(("nan is not enabled, cancel publish blocked\n"));
5056 cmd_data
= (nan_discover_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
5058 WL_ERR(("%s: memory allocation failed\n", __func__
));
5064 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
5066 ret
= wl_cfgvendor_nan_parse_discover_args(wiphy
, data
, len
, cmd_data
);
5068 WL_ERR(("failed to parse nan disc vendor args, ret= %d\n", ret
));
5071 nan_req_resp
.instance_id
= cmd_data
->pub_id
;
5072 WL_INFORM_MEM(("[NAN] cancel publish instance_id=%d\n", cmd_data
->pub_id
));
5074 ret
= wl_cfgnan_cancel_pub_handler(wdev
->netdev
, cfg
, cmd_data
);
5076 WL_ERR(("failed to cancel publish nan instance-id[%d] error[%d]\n",
5077 cmd_data
->pub_id
, ret
));
5081 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_CANCEL_PUBLISH
,
5082 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
5083 wl_cfgvendor_free_disc_cmd_data(cfg
, cmd_data
);
5089 wl_cfgvendor_nan_cancel_subscribe(struct wiphy
*wiphy
,
5090 struct wireless_dev
*wdev
, const void * data
, int len
)
5093 nan_discover_cmd_data_t
*cmd_data
= NULL
;
5094 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5095 nan_hal_resp_t nan_req_resp
;
5097 /* Blocking Cancel_Subscribe if NAN is not enableb */
5098 if (!cfg
->nan_enable
) {
5099 WL_ERR(("nan is not enabled, cancel subscribe blocked\n"));
5103 cmd_data
= MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
5105 WL_ERR(("%s: memory allocation failed\n", __func__
));
5111 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
5113 ret
= wl_cfgvendor_nan_parse_discover_args(wiphy
, data
, len
, cmd_data
);
5115 WL_ERR(("failed to parse nan disc vendor args, ret= %d\n", ret
));
5118 nan_req_resp
.instance_id
= cmd_data
->sub_id
;
5119 WL_INFORM_MEM(("[NAN] cancel subscribe instance_id=%d\n", cmd_data
->sub_id
));
5121 ret
= wl_cfgnan_cancel_sub_handler(wdev
->netdev
, cfg
, cmd_data
);
5123 WL_ERR(("failed to cancel subscribe nan instance-id[%d] error[%d]\n",
5124 cmd_data
->sub_id
, ret
));
5128 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_CANCEL_SUBSCRIBE
,
5129 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
5130 wl_cfgvendor_free_disc_cmd_data(cfg
, cmd_data
);
5136 wl_cfgvendor_nan_transmit(struct wiphy
*wiphy
,
5137 struct wireless_dev
*wdev
, const void * data
, int len
)
5140 nan_discover_cmd_data_t
*cmd_data
= NULL
;
5141 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5142 nan_hal_resp_t nan_req_resp
;
5144 /* Blocking Transmit if NAN is not enable */
5145 if (!cfg
->nan_enable
) {
5146 WL_ERR(("nan is not enabled, transmit blocked\n"));
5150 cmd_data
= (nan_discover_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
5152 WL_ERR(("%s: memory allocation failed\n", __func__
));
5158 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
5160 ret
= wl_cfgvendor_nan_parse_discover_args(wiphy
, data
, len
, cmd_data
);
5162 WL_ERR(("failed to parse nan disc vendor args, ret= %d\n", ret
));
5165 nan_req_resp
.instance_id
= cmd_data
->local_id
;
5166 ret
= wl_cfgnan_transmit_handler(wdev
->netdev
, cfg
, cmd_data
);
5168 WL_ERR(("failed to transmit-followup nan error[%d]\n", ret
));
5172 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_TRANSMIT
,
5173 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
5174 wl_cfgvendor_free_disc_cmd_data(cfg
, cmd_data
);
5180 wl_cfgvendor_nan_get_capablities(struct wiphy
*wiphy
,
5181 struct wireless_dev
*wdev
, const void * data
, int len
)
5184 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5185 nan_hal_resp_t nan_req_resp
;
5189 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
5191 ret
= wl_cfgnan_get_capablities_handler(wdev
->netdev
, cfg
, &nan_req_resp
.capabilities
);
5193 WL_ERR(("Could not get capabilities\n"));
5198 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_GET_CAPABILITIES
,
5199 &nan_req_resp
, ret
, BCME_OK
);
5200 wl_cfgvendor_send_cmd_reply(wiphy
, &nan_req_resp
, sizeof(nan_req_resp
));
5207 wl_cfgvendor_nan_data_path_iface_create(struct wiphy
*wiphy
,
5208 struct wireless_dev
*wdev
, const void * data
, int len
)
5212 nan_datapath_cmd_data_t
*cmd_data
= NULL
;
5213 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5214 nan_hal_resp_t nan_req_resp
;
5215 dhd_pub_t
*dhdp
= wl_cfg80211_get_dhdp(wdev
->netdev
);
5217 if (!cfg
->nan_init_state
) {
5218 WL_ERR(("%s: NAN is not inited or Device doesn't support NAN \n", __func__
));
5223 cmd_data
= (nan_datapath_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
5225 WL_ERR(("%s: memory allocation failed\n", __func__
));
5231 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
5233 ret
= wl_cfgvendor_nan_parse_datapath_args(wiphy
, data
, len
, cmd_data
);
5235 WL_ERR(("failed to parse nan datapath vendor args, ret = %d\n", ret
));
5239 /* Store the iface name to pub data so that it can be used
5242 if ((idx
= wl_cfgnan_get_ndi_idx(cfg
)) < 0) {
5243 WL_ERR(("No free idx for NAN NDI\n"));
5246 wl_cfgnan_add_ndi_data(cfg
, idx
, (char*)cmd_data
->ndp_iface
);
5247 if (cfg
->nan_enable
) { /* new framework Impl, iface create called after nan enab */
5248 wl_cfgnan_data_path_iface_create_delete_handler(wdev
->netdev
,
5249 cfg
, cmd_data
->ndp_iface
,
5250 NAN_WIFI_SUBCMD_DATA_PATH_IFACE_CREATE
, dhdp
->up
);
5251 cfg
->nancfg
.ndi
[idx
].created
= true;
5254 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_DATA_PATH_IFACE_CREATE
,
5255 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
5256 wl_cfgvendor_free_dp_cmd_data(cfg
, cmd_data
);
5262 wl_cfgvendor_nan_data_path_iface_delete(struct wiphy
*wiphy
,
5263 struct wireless_dev
*wdev
, const void * data
, int len
)
5266 nan_datapath_cmd_data_t
*cmd_data
= NULL
;
5267 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5268 nan_hal_resp_t nan_req_resp
;
5269 dhd_pub_t
*dhdp
= wl_cfg80211_get_dhdp(wdev
->netdev
);
5271 if (!cfg
->nan_init_state
) {
5272 WL_ERR(("%s: NAN is not inited or Device doesn't support NAN \n", __func__
));
5273 /* Deinit has taken care of cleaing the virtual iface */
5279 cmd_data
= (nan_datapath_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
5281 WL_ERR(("%s: memory allocation failed\n", __func__
));
5285 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
5286 ret
= wl_cfgvendor_nan_parse_datapath_args(wiphy
, data
, len
, cmd_data
);
5288 WL_ERR(("failed to parse nan datapath vendor args, ret = %d\n", ret
));
5292 ret
= wl_cfgnan_data_path_iface_create_delete_handler(wdev
->netdev
, cfg
,
5293 (char*)cmd_data
->ndp_iface
,
5294 NAN_WIFI_SUBCMD_DATA_PATH_IFACE_DELETE
, dhdp
->up
);
5296 if (ret
== -ENODEV
) {
5297 if (wl_cfgnan_get_ndi_data(cfg
, (char*)cmd_data
->ndp_iface
) != NULL
) {
5298 /* NDIs have been removed by the NAN disable command */
5299 WL_DBG(("NDI removed by nan_disable\n"));
5303 WL_ERR(("failed to delete ndp iface [%d]\n", ret
));
5308 if (cfg
->nan_init_state
) {
5309 /* After successful delete of interface, clear up the ndi data */
5310 if (wl_cfgnan_del_ndi_data(cfg
, (char*)cmd_data
->ndp_iface
) < 0) {
5311 WL_ERR(("Failed to find matching data for ndi:%s\n",
5312 (char*)cmd_data
->ndp_iface
));
5316 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_DATA_PATH_IFACE_DELETE
,
5317 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
5318 wl_cfgvendor_free_dp_cmd_data(cfg
, cmd_data
);
5324 wl_cfgvendor_nan_data_path_request(struct wiphy
*wiphy
,
5325 struct wireless_dev
*wdev
, const void * data
, int len
)
5328 nan_datapath_cmd_data_t
*cmd_data
= NULL
;
5329 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5330 nan_hal_resp_t nan_req_resp
;
5331 uint8 ndp_instance_id
= 0;
5333 if (!cfg
->nan_enable
) {
5334 WL_ERR(("nan is not enabled, nan data path request blocked\n"));
5340 cmd_data
= (nan_datapath_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
5342 WL_ERR(("%s: memory allocation failed\n", __func__
));
5347 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
5348 ret
= wl_cfgvendor_nan_parse_datapath_args(wiphy
, data
, len
, cmd_data
);
5350 WL_ERR(("failed to parse nan datapath vendor args, ret = %d\n", ret
));
5354 ret
= wl_cfgnan_data_path_request_handler(wdev
->netdev
, cfg
,
5355 cmd_data
, &ndp_instance_id
);
5357 WL_ERR(("failed to request nan data path [%d]\n", ret
));
5361 if (cmd_data
->status
== BCME_OK
) {
5362 nan_req_resp
.ndp_instance_id
= cmd_data
->ndp_instance_id
;
5364 nan_req_resp
.ndp_instance_id
= 0;
5367 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_DATA_PATH_REQUEST
,
5368 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
5369 wl_cfgvendor_free_dp_cmd_data(cfg
, cmd_data
);
5375 wl_cfgvendor_nan_data_path_response(struct wiphy
*wiphy
,
5376 struct wireless_dev
*wdev
, const void * data
, int len
)
5379 nan_datapath_cmd_data_t
*cmd_data
= NULL
;
5380 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5381 nan_hal_resp_t nan_req_resp
;
5383 if (!cfg
->nan_enable
) {
5384 WL_ERR(("nan is not enabled, nan data path response blocked\n"));
5389 cmd_data
= (nan_datapath_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
5391 WL_ERR(("%s: memory allocation failed\n", __func__
));
5396 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
5397 ret
= wl_cfgvendor_nan_parse_datapath_args(wiphy
, data
, len
, cmd_data
);
5399 WL_ERR(("failed to parse nan datapath vendor args, ret = %d\n", ret
));
5402 ret
= wl_cfgnan_data_path_response_handler(wdev
->netdev
, cfg
, cmd_data
);
5404 WL_ERR(("failed to response nan data path [%d]\n", ret
));
5408 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_DATA_PATH_RESPONSE
,
5409 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
5410 wl_cfgvendor_free_dp_cmd_data(cfg
, cmd_data
);
5416 wl_cfgvendor_nan_data_path_end(struct wiphy
*wiphy
,
5417 struct wireless_dev
*wdev
, const void * data
, int len
)
5420 nan_datapath_cmd_data_t
*cmd_data
= NULL
;
5421 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5422 nan_hal_resp_t nan_req_resp
;
5425 if (!cfg
->nan_enable
) {
5426 WL_ERR(("nan is not enabled, nan data path end blocked\n"));
5430 cmd_data
= (nan_datapath_cmd_data_t
*)MALLOCZ(cfg
->osh
, sizeof(*cmd_data
));
5432 WL_ERR(("%s: memory allocation failed\n", __func__
));
5437 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
5438 ret
= wl_cfgvendor_nan_parse_datapath_args(wiphy
, data
, len
, cmd_data
);
5440 WL_ERR(("failed to parse nan datapath vendor args, ret = %d\n", ret
));
5443 ret
= wl_cfgnan_data_path_end_handler(wdev
->netdev
, cfg
, cmd_data
);
5445 WL_ERR(("failed to end nan data path [%d]\n", ret
));
5449 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_DATA_PATH_END
,
5450 &nan_req_resp
, ret
, cmd_data
? cmd_data
->status
: BCME_OK
);
5451 wl_cfgvendor_free_dp_cmd_data(cfg
, cmd_data
);
5456 #ifdef WL_NAN_DISC_CACHE
5458 wl_cfgvendor_nan_data_path_sec_info(struct wiphy
*wiphy
,
5459 struct wireless_dev
*wdev
, const void *data
, int len
)
5462 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5463 nan_hal_resp_t nan_req_resp
;
5464 nan_datapath_sec_info_cmd_data_t
*cmd_data
= NULL
;
5465 dhd_pub_t
*dhdp
= wl_cfg80211_get_dhdp(wdev
->netdev
);
5468 if (!cfg
->nan_enable
) {
5469 WL_ERR(("nan is not enabled\n"));
5470 ret
= BCME_UNSUPPORTED
;
5473 cmd_data
= MALLOCZ(dhdp
->osh
, sizeof(*cmd_data
));
5475 WL_ERR(("%s: memory allocation failed\n", __func__
));
5480 ret
= wl_cfgvendor_nan_parse_dp_sec_info_args(wiphy
, data
, len
, cmd_data
);
5482 WL_ERR(("failed to parse sec info args\n"));
5485 memset(&nan_req_resp
, 0, sizeof(nan_req_resp
));
5486 ret
= wl_cfgnan_sec_info_handler(cfg
, cmd_data
, &nan_req_resp
);
5488 WL_ERR(("failed to retrieve svc hash/pub nmi error[%d]\n", ret
));
5492 ret
= wl_cfgvendor_nan_cmd_reply(wiphy
, NAN_WIFI_SUBCMD_DATA_PATH_SEC_INFO
,
5493 &nan_req_resp
, ret
, BCME_OK
);
5495 MFREE(dhdp
->osh
, cmd_data
, sizeof(*cmd_data
));
5500 #endif /* WL_NAN_DISC_CACHE */
5503 wl_cfgvendor_nan_version_info(struct wiphy
*wiphy
,
5504 struct wireless_dev
*wdev
, const void *data
, int len
)
5507 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5508 uint32 version
= NAN_HAL_VERSION_1
;
5511 WL_DBG(("Enter %s version %d\n", __FUNCTION__
, version
));
5512 ret
= wl_cfgvendor_send_cmd_reply(wiphy
, &version
, sizeof(version
));
5518 #ifdef LINKSTAT_SUPPORT
5523 #define HEADER_SIZE sizeof(ver_len)
5525 static int wl_cfgvendor_lstats_get_bcn_mbss(char *buf
, uint32
*rxbeaconmbss
)
5527 wl_cnt_info_t
*cbuf
= (wl_cnt_info_t
*)buf
;
5530 if ((cnt
= (const void *)bcm_get_data_from_xtlv_buf(cbuf
->data
, cbuf
->datalen
,
5531 WL_CNT_XTLV_CNTV_LE10_UCODE
, NULL
, BCM_XTLV_OPTION_ALIGN32
)) != NULL
) {
5532 *rxbeaconmbss
= ((const wl_cnt_v_le10_mcst_t
*)cnt
)->rxbeaconmbss
;
5533 } else if ((cnt
= (const void *)bcm_get_data_from_xtlv_buf(cbuf
->data
, cbuf
->datalen
,
5534 WL_CNT_XTLV_LT40_UCODE_V1
, NULL
, BCM_XTLV_OPTION_ALIGN32
)) != NULL
) {
5535 *rxbeaconmbss
= ((const wl_cnt_lt40mcst_v1_t
*)cnt
)->rxbeaconmbss
;
5536 } else if ((cnt
= (const void *)bcm_get_data_from_xtlv_buf(cbuf
->data
, cbuf
->datalen
,
5537 WL_CNT_XTLV_GE40_UCODE_V1
, NULL
, BCM_XTLV_OPTION_ALIGN32
)) != NULL
) {
5538 *rxbeaconmbss
= ((const wl_cnt_ge40mcst_v1_t
*)cnt
)->rxbeaconmbss
;
5539 } else if ((cnt
= (const void *)bcm_get_data_from_xtlv_buf(cbuf
->data
, cbuf
->datalen
,
5540 WL_CNT_XTLV_GE80_UCODE_V1
, NULL
, BCM_XTLV_OPTION_ALIGN32
)) != NULL
) {
5541 *rxbeaconmbss
= ((const wl_cnt_ge80mcst_v1_t
*)cnt
)->rxbeaconmbss
;
5544 return BCME_NOTFOUND
;
5550 static int wl_cfgvendor_lstats_get_info(struct wiphy
*wiphy
,
5551 struct wireless_dev
*wdev
, const void *data
, int len
)
5553 static char iovar_buf
[WLC_IOCTL_MAXLEN
];
5554 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5556 wifi_radio_stat
*radio
;
5557 wifi_radio_stat_h radio_h
;
5558 wl_wme_cnt_t
*wl_wme_cnt
;
5559 const wl_cnt_wlc_t
*wlc_cnt
;
5561 char *output
= NULL
;
5562 char *outdata
= NULL
;
5563 wifi_rate_stat_v1
*p_wifi_rate_stat_v1
= NULL
;
5564 wifi_rate_stat
*p_wifi_rate_stat
= NULL
;
5566 uint32 rxbeaconmbss
;
5567 wifi_iface_stat iface
;
5568 wlc_rev_info_t revinfo
;
5569 #ifdef CONFIG_COMPAT
5570 compat_wifi_iface_stat compat_iface
;
5571 int compat_task_state
= is_compat_task();
5572 #endif /* CONFIG_COMPAT */
5574 WL_INFORM_MEM(("%s: Enter \n", __func__
));
5575 RETURN_EIO_IF_NOT_UP(cfg
);
5577 /* Get the device rev info */
5578 memset(&revinfo
, 0, sizeof(revinfo
));
5579 err
= wldev_ioctl_get(bcmcfg_to_prmry_ndev(cfg
), WLC_GET_REVINFO
, &revinfo
,
5581 if (err
!= BCME_OK
) {
5585 outdata
= (void *)MALLOCZ(cfg
->osh
, WLC_IOCTL_MAXLEN
);
5586 if (outdata
== NULL
) {
5587 WL_ERR(("%s: alloc failed\n", __func__
));
5591 memset(&scbval
, 0, sizeof(scb_val_t
));
5592 memset(outdata
, 0, WLC_IOCTL_MAXLEN
);
5595 err
= wldev_iovar_getbuf(bcmcfg_to_prmry_ndev(cfg
), "radiostat", NULL
, 0,
5596 iovar_buf
, WLC_IOCTL_MAXLEN
, NULL
);
5597 if (err
!= BCME_OK
&& err
!= BCME_UNSUPPORTED
) {
5598 WL_ERR(("error (%d) - size = %zu\n", err
, sizeof(wifi_radio_stat
)));
5601 radio
= (wifi_radio_stat
*)iovar_buf
;
5603 memset(&radio_h
, 0, sizeof(wifi_radio_stat_h
));
5604 radio_h
.on_time
= radio
->on_time
;
5605 radio_h
.tx_time
= radio
->tx_time
;
5606 radio_h
.rx_time
= radio
->rx_time
;
5607 radio_h
.on_time_scan
= radio
->on_time_scan
;
5608 radio_h
.on_time_nbd
= radio
->on_time_nbd
;
5609 radio_h
.on_time_gscan
= radio
->on_time_gscan
;
5610 radio_h
.on_time_roam_scan
= radio
->on_time_roam_scan
;
5611 radio_h
.on_time_pno_scan
= radio
->on_time_pno_scan
;
5612 radio_h
.on_time_hs20
= radio
->on_time_hs20
;
5613 radio_h
.num_channels
= NUM_CHAN
;
5615 memcpy(output
, &radio_h
, sizeof(wifi_radio_stat_h
));
5617 output
+= sizeof(wifi_radio_stat_h
);
5618 output
+= (NUM_CHAN
* sizeof(wifi_channel_stat
));
5620 err
= wldev_iovar_getbuf(bcmcfg_to_prmry_ndev(cfg
), "wme_counters", NULL
, 0,
5621 iovar_buf
, WLC_IOCTL_MAXLEN
, NULL
);
5622 if (unlikely(err
)) {
5623 WL_ERR(("error (%d)\n", err
));
5626 wl_wme_cnt
= (wl_wme_cnt_t
*)iovar_buf
;
5628 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_VO
].ac
, WIFI_AC_VO
);
5629 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_VO
].tx_mpdu
, wl_wme_cnt
->tx
[AC_VO
].packets
);
5630 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_VO
].rx_mpdu
, wl_wme_cnt
->rx
[AC_VO
].packets
);
5631 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_VO
].mpdu_lost
,
5632 wl_wme_cnt
->tx_failed
[WIFI_AC_VO
].packets
);
5634 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_VI
].ac
, WIFI_AC_VI
);
5635 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_VI
].tx_mpdu
, wl_wme_cnt
->tx
[AC_VI
].packets
);
5636 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_VI
].rx_mpdu
, wl_wme_cnt
->rx
[AC_VI
].packets
);
5637 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_VI
].mpdu_lost
,
5638 wl_wme_cnt
->tx_failed
[WIFI_AC_VI
].packets
);
5640 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_BE
].ac
, WIFI_AC_BE
);
5641 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_BE
].tx_mpdu
, wl_wme_cnt
->tx
[AC_BE
].packets
);
5642 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_BE
].rx_mpdu
, wl_wme_cnt
->rx
[AC_BE
].packets
);
5643 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_BE
].mpdu_lost
,
5644 wl_wme_cnt
->tx_failed
[WIFI_AC_BE
].packets
);
5646 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_BK
].ac
, WIFI_AC_BK
);
5647 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_BK
].tx_mpdu
, wl_wme_cnt
->tx
[AC_BK
].packets
);
5648 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_BK
].rx_mpdu
, wl_wme_cnt
->rx
[AC_BK
].packets
);
5649 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_BK
].mpdu_lost
,
5650 wl_wme_cnt
->tx_failed
[WIFI_AC_BK
].packets
);
5652 err
= wldev_iovar_getbuf(bcmcfg_to_prmry_ndev(cfg
), "counters", NULL
, 0,
5653 iovar_buf
, WLC_IOCTL_MAXLEN
, NULL
);
5654 if (unlikely(err
)) {
5655 WL_ERR(("error (%d) - size = %zu\n", err
, sizeof(wl_cnt_wlc_t
)));
5659 CHK_CNTBUF_DATALEN(iovar_buf
, WLC_IOCTL_MAXLEN
);
5660 /* Translate traditional (ver <= 10) counters struct to new xtlv type struct */
5661 err
= wl_cntbuf_to_xtlv_format(NULL
, iovar_buf
, WLC_IOCTL_MAXLEN
, revinfo
.corerev
);
5662 if (err
!= BCME_OK
) {
5663 WL_ERR(("%s wl_cntbuf_to_xtlv_format ERR %d\n",
5664 __FUNCTION__
, err
));
5668 if (!(wlc_cnt
= GET_WLCCNT_FROM_CNTBUF(iovar_buf
))) {
5669 WL_ERR(("%s wlc_cnt NULL!\n", __FUNCTION__
));
5674 COMPAT_ASSIGN_VALUE(iface
, ac
[WIFI_AC_BE
].retries
, wlc_cnt
->txretry
);
5676 err
= wl_cfgvendor_lstats_get_bcn_mbss(iovar_buf
, &rxbeaconmbss
);
5677 if (unlikely(err
)) {
5678 WL_ERR(("get_bcn_mbss error (%d)\n", err
));
5682 err
= wldev_get_rssi(bcmcfg_to_prmry_ndev(cfg
), &scbval
);
5683 if (unlikely(err
)) {
5684 WL_ERR(("get_rssi error (%d)\n", err
));
5688 COMPAT_ASSIGN_VALUE(iface
, beacon_rx
, rxbeaconmbss
);
5689 COMPAT_ASSIGN_VALUE(iface
, rssi_mgmt
, scbval
.val
);
5690 COMPAT_ASSIGN_VALUE(iface
, num_peers
, NUM_PEER
);
5691 COMPAT_ASSIGN_VALUE(iface
, peer_info
->num_rate
, NUM_RATE
);
5693 #ifdef CONFIG_COMPAT
5694 if (compat_task_state
) {
5695 memcpy(output
, &compat_iface
, sizeof(compat_iface
));
5696 output
+= (sizeof(compat_iface
) - sizeof(wifi_rate_stat
));
5698 #endif /* CONFIG_COMPAT */
5700 memcpy(output
, &iface
, sizeof(iface
));
5701 output
+= (sizeof(iface
) - sizeof(wifi_rate_stat
));
5704 err
= wldev_iovar_getbuf(bcmcfg_to_prmry_ndev(cfg
), "ratestat", NULL
, 0,
5705 iovar_buf
, WLC_IOCTL_MAXLEN
, NULL
);
5706 if (err
!= BCME_OK
&& err
!= BCME_UNSUPPORTED
) {
5707 WL_ERR(("error (%d) - size = %zu\n", err
, NUM_RATE
*sizeof(wifi_rate_stat
)));
5710 for (i
= 0; i
< NUM_RATE
; i
++) {
5712 (wifi_rate_stat
*)(iovar_buf
+ i
*sizeof(wifi_rate_stat
));
5713 p_wifi_rate_stat_v1
= (wifi_rate_stat_v1
*)output
;
5714 p_wifi_rate_stat_v1
->rate
.preamble
= p_wifi_rate_stat
->rate
.preamble
;
5715 p_wifi_rate_stat_v1
->rate
.nss
= p_wifi_rate_stat
->rate
.nss
;
5716 p_wifi_rate_stat_v1
->rate
.bw
= p_wifi_rate_stat
->rate
.bw
;
5717 p_wifi_rate_stat_v1
->rate
.rateMcsIdx
= p_wifi_rate_stat
->rate
.rateMcsIdx
;
5718 p_wifi_rate_stat_v1
->rate
.reserved
= p_wifi_rate_stat
->rate
.reserved
;
5719 p_wifi_rate_stat_v1
->rate
.bitrate
= p_wifi_rate_stat
->rate
.bitrate
;
5720 p_wifi_rate_stat_v1
->tx_mpdu
= p_wifi_rate_stat
->tx_mpdu
;
5721 p_wifi_rate_stat_v1
->rx_mpdu
= p_wifi_rate_stat
->rx_mpdu
;
5722 p_wifi_rate_stat_v1
->mpdu_lost
= p_wifi_rate_stat
->mpdu_lost
;
5723 p_wifi_rate_stat_v1
->retries
= p_wifi_rate_stat
->retries
;
5724 p_wifi_rate_stat_v1
->retries_short
= p_wifi_rate_stat
->retries_short
;
5725 p_wifi_rate_stat_v1
->retries_long
= p_wifi_rate_stat
->retries_long
;
5726 output
= (char *) &(p_wifi_rate_stat_v1
->retries_long
);
5727 output
+= sizeof(p_wifi_rate_stat_v1
->retries_long
);
5730 total_len
= sizeof(wifi_radio_stat_h
) +
5731 NUM_CHAN
* sizeof(wifi_channel_stat
);
5733 #ifdef CONFIG_COMPAT
5734 if (compat_task_state
) {
5735 total_len
+= sizeof(compat_wifi_iface_stat
);
5737 #endif /* CONFIG_COMPAT */
5739 total_len
+= sizeof(wifi_iface_stat
);
5742 total_len
= total_len
- sizeof(wifi_peer_info
) +
5743 NUM_PEER
* (sizeof(wifi_peer_info
) - sizeof(wifi_rate_stat_v1
) +
5744 NUM_RATE
* sizeof(wifi_rate_stat_v1
));
5746 if (total_len
> WLC_IOCTL_MAXLEN
) {
5747 WL_ERR(("Error! total_len:%d is unexpected value\n", total_len
));
5751 err
= wl_cfgvendor_send_cmd_reply(wiphy
, outdata
, total_len
);
5754 WL_ERR(("Vendor Command reply failed ret:%d \n", err
));
5758 MFREE(cfg
->osh
, outdata
, WLC_IOCTL_MAXLEN
);
5762 #endif /* LINKSTAT_SUPPORT */
5765 static int wl_cfgvendor_dbg_start_logging(struct wiphy
*wiphy
,
5766 struct wireless_dev
*wdev
, const void *data
, int len
)
5768 int ret
= BCME_OK
, rem
, type
;
5769 char ring_name
[DBGRING_NAME_MAX
] = {0};
5770 int log_level
= 0, flags
= 0, time_intval
= 0, threshold
= 0;
5771 const struct nlattr
*iter
;
5772 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5773 dhd_pub_t
*dhd_pub
= cfg
->pub
;
5774 nla_for_each_attr(iter
, data
, len
, rem
) {
5775 type
= nla_type(iter
);
5777 case DEBUG_ATTRIBUTE_RING_NAME
:
5778 strncpy(ring_name
, nla_data(iter
),
5779 MIN(sizeof(ring_name
) -1, nla_len(iter
)));
5781 case DEBUG_ATTRIBUTE_LOG_LEVEL
:
5782 log_level
= nla_get_u32(iter
);
5784 case DEBUG_ATTRIBUTE_RING_FLAGS
:
5785 flags
= nla_get_u32(iter
);
5787 case DEBUG_ATTRIBUTE_LOG_TIME_INTVAL
:
5788 time_intval
= nla_get_u32(iter
);
5790 case DEBUG_ATTRIBUTE_LOG_MIN_DATA_SIZE
:
5791 threshold
= nla_get_u32(iter
);
5794 WL_ERR(("Unknown type: %d\n", type
));
5800 ret
= dhd_os_start_logging(dhd_pub
, ring_name
, log_level
, flags
, time_intval
, threshold
);
5802 WL_ERR(("start_logging is failed ret: %d\n", ret
));
5808 static int wl_cfgvendor_dbg_reset_logging(struct wiphy
*wiphy
,
5809 struct wireless_dev
*wdev
, const void *data
, int len
)
5812 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5813 dhd_pub_t
*dhd_pub
= cfg
->pub
;
5815 ret
= dhd_os_reset_logging(dhd_pub
);
5817 WL_ERR(("reset logging is failed ret: %d\n", ret
));
5824 wl_cfgvendor_dbg_trigger_mem_dump(struct wiphy
*wiphy
,
5825 struct wireless_dev
*wdev
, const void *data
, int len
)
5829 struct sk_buff
*skb
;
5830 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5831 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
5833 dhdp
->memdump_type
= DUMP_TYPE_CFG_VENDOR_TRIGGERED
;
5834 ret
= dhd_os_socram_dump(bcmcfg_to_prmry_ndev(cfg
), &alloc_len
);
5836 WL_ERR(("failed to call dhd_os_socram_dump : %d\n", ret
));
5839 /* Alloc the SKB for vendor_event */
5840 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, 100);
5842 WL_ERR(("skb allocation is failed\n"));
5846 nla_put_u32(skb
, DEBUG_ATTRIBUTE_FW_DUMP_LEN
, alloc_len
);
5848 ret
= cfg80211_vendor_cmd_reply(skb
);
5851 WL_ERR(("Vendor Command reply failed ret:%d \n", ret
));
5859 wl_cfgvendor_dbg_get_mem_dump(struct wiphy
*wiphy
,
5860 struct wireless_dev
*wdev
, const void *data
, int len
)
5862 int ret
= BCME_OK
, rem
, type
;
5864 uintptr_t user_buf
= (uintptr_t)NULL
;
5865 const struct nlattr
*iter
;
5866 char *mem_buf
= NULL
;
5867 struct sk_buff
*skb
;
5868 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5870 nla_for_each_attr(iter
, data
, len
, rem
) {
5871 type
= nla_type(iter
);
5873 case DEBUG_ATTRIBUTE_FW_DUMP_LEN
:
5874 /* Check if the iter is valid and
5875 * buffer length is not already initialized.
5877 if ((nla_len(iter
) == sizeof(uint32
)) &&
5879 buf_len
= nla_get_u32(iter
);
5889 case DEBUG_ATTRIBUTE_FW_DUMP_DATA
:
5890 if (nla_len(iter
) != sizeof(uint64
)) {
5891 WL_ERR(("Invalid len\n"));
5895 user_buf
= (uintptr_t)nla_get_u64(iter
);
5902 WL_ERR(("Unknown type: %d\n", type
));
5907 if (buf_len
> 0 && user_buf
) {
5908 mem_buf
= vmalloc(buf_len
);
5910 WL_ERR(("failed to allocate mem_buf with size : %d\n", buf_len
));
5914 ret
= dhd_os_get_socram_dump(bcmcfg_to_prmry_ndev(cfg
), &mem_buf
, &buf_len
);
5916 WL_ERR(("failed to get_socram_dump : %d\n", ret
));
5919 #ifdef CONFIG_COMPAT
5920 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0))
5921 if (in_compat_syscall()) {
5923 if (is_compat_task()) {
5924 #endif /* LINUX_VER >= 4.6 */
5925 void * usr_ptr
= compat_ptr((uintptr_t) user_buf
);
5926 ret
= copy_to_user(usr_ptr
, mem_buf
, buf_len
);
5928 WL_ERR(("failed to copy memdump into user buffer : %d\n", ret
));
5933 #endif /* CONFIG_COMPAT */
5935 ret
= copy_to_user((void*)user_buf
, mem_buf
, buf_len
);
5937 WL_ERR(("failed to copy memdump into user buffer : %d\n", ret
));
5941 /* Alloc the SKB for vendor_event */
5942 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, 100);
5944 WL_ERR(("skb allocation is failed\n"));
5948 /* Indicate the memdump is succesfully copied */
5949 nla_put(skb
, DEBUG_ATTRIBUTE_FW_DUMP_DATA
, sizeof(ret
), &ret
);
5951 ret
= cfg80211_vendor_cmd_reply(skb
);
5954 WL_ERR(("Vendor Command reply failed ret:%d \n", ret
));
5964 static int wl_cfgvendor_dbg_get_ring_status(struct wiphy
*wiphy
,
5965 struct wireless_dev
*wdev
, const void *data
, int len
)
5970 struct sk_buff
*skb
;
5971 dhd_dbg_ring_status_t dbg_ring_status
[DEBUG_RING_ID_MAX
];
5972 dhd_dbg_ring_status_t ring_status
;
5973 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5974 dhd_pub_t
*dhd_pub
= cfg
->pub
;
5975 memset(dbg_ring_status
, 0, DBG_RING_STATUS_SIZE
* DEBUG_RING_ID_MAX
);
5977 for (ring_id
= DEBUG_RING_ID_INVALID
+ 1; ring_id
< DEBUG_RING_ID_MAX
; ring_id
++) {
5978 ret
= dhd_os_get_ring_status(dhd_pub
, ring_id
, &ring_status
);
5979 if (ret
== BCME_NOTFOUND
) {
5980 WL_DBG(("The ring (%d) is not found \n", ring_id
));
5981 } else if (ret
== BCME_OK
) {
5982 dbg_ring_status
[ring_cnt
++] = ring_status
;
5985 /* Alloc the SKB for vendor_event */
5986 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
,
5987 (DBG_RING_STATUS_SIZE
* ring_cnt
) + 100);
5989 WL_ERR(("skb allocation is failed\n"));
5994 nla_put_u32(skb
, DEBUG_ATTRIBUTE_RING_NUM
, ring_cnt
);
5995 for (i
= 0; i
< ring_cnt
; i
++) {
5996 nla_put(skb
, DEBUG_ATTRIBUTE_RING_STATUS
, DBG_RING_STATUS_SIZE
,
5997 &dbg_ring_status
[i
]);
5999 ret
= cfg80211_vendor_cmd_reply(skb
);
6002 WL_ERR(("Vendor Command reply failed ret:%d \n", ret
));
6008 static int wl_cfgvendor_dbg_get_ring_data(struct wiphy
*wiphy
,
6009 struct wireless_dev
*wdev
, const void *data
, int len
)
6011 int ret
= BCME_OK
, rem
, type
;
6012 char ring_name
[DBGRING_NAME_MAX
] = {0};
6013 const struct nlattr
*iter
;
6014 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6015 dhd_pub_t
*dhd_pub
= cfg
->pub
;
6017 nla_for_each_attr(iter
, data
, len
, rem
) {
6018 type
= nla_type(iter
);
6020 case DEBUG_ATTRIBUTE_RING_NAME
:
6021 strncpy(ring_name
, nla_data(iter
),
6022 MIN(sizeof(ring_name
) -1, nla_len(iter
)));
6025 WL_ERR(("Unknown type: %d\n", type
));
6030 ret
= dhd_os_trigger_get_ring_data(dhd_pub
, ring_name
);
6032 WL_ERR(("trigger_get_data failed ret:%d\n", ret
));
6037 #endif /* DEBUGABILITY */
6039 static int wl_cfgvendor_dbg_get_feature(struct wiphy
*wiphy
,
6040 struct wireless_dev
*wdev
, const void *data
, int len
)
6043 u32 supported_features
= 0;
6044 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6045 dhd_pub_t
*dhd_pub
= cfg
->pub
;
6047 ret
= dhd_os_dbg_get_feature(dhd_pub
, &supported_features
);
6049 WL_ERR(("dbg_get_feature failed ret:%d\n", ret
));
6052 ret
= wl_cfgvendor_send_cmd_reply(wiphy
, &supported_features
,
6053 sizeof(supported_features
));
6059 static void wl_cfgvendor_dbg_ring_send_evt(void *ctx
,
6060 const int ring_id
, const void *data
, const uint32 len
,
6061 const dhd_dbg_ring_status_t ring_status
)
6063 struct net_device
*ndev
= ctx
;
6064 struct wiphy
*wiphy
;
6066 struct sk_buff
*skb
;
6068 WL_ERR(("ndev is NULL\n"));
6071 kflags
= in_atomic() ? GFP_ATOMIC
: GFP_KERNEL
;
6072 wiphy
= ndev
->ieee80211_ptr
->wiphy
;
6073 /* Alloc the SKB for vendor_event */
6074 #if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
6075 LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
6076 skb
= cfg80211_vendor_event_alloc(wiphy
, NULL
, len
+ 100,
6077 GOOGLE_DEBUG_RING_EVENT
, kflags
);
6079 skb
= cfg80211_vendor_event_alloc(wiphy
, len
+ 100,
6080 GOOGLE_DEBUG_RING_EVENT
, kflags
);
6081 #endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
6082 /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */
6084 WL_ERR(("skb alloc failed"));
6087 nla_put(skb
, DEBUG_ATTRIBUTE_RING_STATUS
, sizeof(ring_status
), &ring_status
);
6088 nla_put(skb
, DEBUG_ATTRIBUTE_RING_DATA
, len
, data
);
6089 cfg80211_vendor_event(skb
, kflags
);
6092 static void wl_cfgvendor_dbg_send_urgent_evt(void *ctx
, const void *data
,
6093 const uint32 len
, const uint32 fw_len
)
6095 struct net_device
*ndev
= ctx
;
6096 struct wiphy
*wiphy
;
6098 struct sk_buff
*skb
;
6100 WL_ERR(("ndev is NULL\n"));
6103 kflags
= in_atomic() ? GFP_ATOMIC
: GFP_KERNEL
;
6104 wiphy
= ndev
->ieee80211_ptr
->wiphy
;
6105 /* Alloc the SKB for vendor_event */
6106 #if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
6107 LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
6108 skb
= cfg80211_vendor_event_alloc(wiphy
, NULL
, len
+ 100,
6109 GOOGLE_FW_DUMP_EVENT
, kflags
);
6111 skb
= cfg80211_vendor_event_alloc(wiphy
, len
+ 100,
6112 GOOGLE_FW_DUMP_EVENT
, kflags
);
6113 #endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
6114 /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */
6116 WL_ERR(("skb alloc failed"));
6119 nla_put_u32(skb
, DEBUG_ATTRIBUTE_FW_DUMP_LEN
, fw_len
);
6120 nla_put(skb
, DEBUG_ATTRIBUTE_RING_DATA
, len
, data
);
6121 cfg80211_vendor_event(skb
, kflags
);
6123 #endif /* DEBUGABILITY */
6125 static int wl_cfgvendor_dbg_get_version(struct wiphy
*wiphy
,
6126 struct wireless_dev
*wdev
, const void *data
, int len
)
6128 int ret
= BCME_OK
, rem
, type
;
6130 bool dhd_ver
= FALSE
;
6132 const struct nlattr
*iter
;
6133 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6135 buf_ptr
= (char *)MALLOCZ(cfg
->osh
, buf_len
);
6137 WL_ERR(("failed to allocate the buffer for version n"));
6141 nla_for_each_attr(iter
, data
, len
, rem
) {
6142 type
= nla_type(iter
);
6144 case DEBUG_ATTRIBUTE_GET_DRIVER
:
6147 case DEBUG_ATTRIBUTE_GET_FW
:
6151 WL_ERR(("Unknown type: %d\n", type
));
6156 ret
= dhd_os_get_version(bcmcfg_to_prmry_ndev(cfg
), dhd_ver
, &buf_ptr
, buf_len
);
6158 WL_ERR(("failed to get the version %d\n", ret
));
6161 ret
= wl_cfgvendor_send_cmd_reply(wiphy
, buf_ptr
, strlen(buf_ptr
));
6163 MFREE(cfg
->osh
, buf_ptr
, buf_len
);
6168 static int wl_cfgvendor_dbg_start_pkt_fate_monitoring(struct wiphy
*wiphy
,
6169 struct wireless_dev
*wdev
, const void *data
, int len
)
6171 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6172 dhd_pub_t
*dhd_pub
= cfg
->pub
;
6175 ret
= dhd_os_dbg_attach_pkt_monitor(dhd_pub
);
6176 if (unlikely(ret
)) {
6177 WL_ERR(("failed to start pkt fate monitoring, ret=%d", ret
));
6183 typedef int (*dbg_mon_get_pkts_t
) (dhd_pub_t
*dhdp
, void __user
*user_buf
,
6184 uint16 req_count
, uint16
*resp_count
);
6186 static int __wl_cfgvendor_dbg_get_pkt_fates(struct wiphy
*wiphy
,
6187 const void *data
, int len
, dbg_mon_get_pkts_t dbg_mon_get_pkts
)
6189 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6190 dhd_pub_t
*dhd_pub
= cfg
->pub
;
6191 struct sk_buff
*skb
= NULL
;
6192 const struct nlattr
*iter
;
6193 void __user
*user_buf
= NULL
;
6194 uint16 req_count
= 0, resp_count
= 0;
6195 int ret
, tmp
, type
, mem_needed
;
6197 nla_for_each_attr(iter
, data
, len
, tmp
) {
6198 type
= nla_type(iter
);
6200 case DEBUG_ATTRIBUTE_PKT_FATE_NUM
:
6201 req_count
= nla_get_u32(iter
);
6203 case DEBUG_ATTRIBUTE_PKT_FATE_DATA
:
6204 user_buf
= (void __user
*)(unsigned long) nla_get_u64(iter
);
6207 WL_ERR(("%s: no such attribute %d\n", __FUNCTION__
, type
));
6213 if (!req_count
|| !user_buf
) {
6214 WL_ERR(("%s: invalid request, user_buf=%p, req_count=%u\n",
6215 __FUNCTION__
, user_buf
, req_count
));
6220 ret
= dbg_mon_get_pkts(dhd_pub
, user_buf
, req_count
, &resp_count
);
6221 if (unlikely(ret
)) {
6222 WL_ERR(("failed to get packets, ret:%d \n", ret
));
6226 mem_needed
= VENDOR_REPLY_OVERHEAD
+ ATTRIBUTE_U32_LEN
;
6227 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, mem_needed
);
6228 if (unlikely(!skb
)) {
6229 WL_ERR(("skb alloc failed"));
6234 nla_put_u32(skb
, DEBUG_ATTRIBUTE_PKT_FATE_NUM
, resp_count
);
6236 ret
= cfg80211_vendor_cmd_reply(skb
);
6237 if (unlikely(ret
)) {
6238 WL_ERR(("vendor Command reply failed ret:%d \n", ret
));
6245 static int wl_cfgvendor_dbg_get_tx_pkt_fates(struct wiphy
*wiphy
,
6246 struct wireless_dev
*wdev
, const void *data
, int len
)
6250 ret
= __wl_cfgvendor_dbg_get_pkt_fates(wiphy
, data
, len
,
6251 dhd_os_dbg_monitor_get_tx_pkts
);
6252 if (unlikely(ret
)) {
6253 WL_ERR(("failed to get tx packets, ret:%d \n", ret
));
6259 static int wl_cfgvendor_dbg_get_rx_pkt_fates(struct wiphy
*wiphy
,
6260 struct wireless_dev
*wdev
, const void *data
, int len
)
6264 ret
= __wl_cfgvendor_dbg_get_pkt_fates(wiphy
, data
, len
,
6265 dhd_os_dbg_monitor_get_rx_pkts
);
6266 if (unlikely(ret
)) {
6267 WL_ERR(("failed to get rx packets, ret:%d \n", ret
));
6272 #endif /* DBG_PKT_MON */
6275 static int wl_cfgvendor_start_mkeep_alive(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
6276 const void *data
, int len
)
6278 /* max size of IP packet for keep alive */
6279 const int MKEEP_ALIVE_IP_PKT_MAX
= 256;
6281 int ret
= BCME_OK
, rem
, type
;
6282 uint8 mkeep_alive_id
= 0;
6283 uint8
*ip_pkt
= NULL
;
6284 uint16 ip_pkt_len
= 0;
6285 uint8 src_mac
[ETHER_ADDR_LEN
];
6286 uint8 dst_mac
[ETHER_ADDR_LEN
];
6287 uint32 period_msec
= 0;
6288 const struct nlattr
*iter
;
6289 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6290 dhd_pub_t
*dhd_pub
= cfg
->pub
;
6292 nla_for_each_attr(iter
, data
, len
, rem
) {
6293 type
= nla_type(iter
);
6295 case MKEEP_ALIVE_ATTRIBUTE_ID
:
6296 mkeep_alive_id
= nla_get_u8(iter
);
6298 case MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN
:
6299 ip_pkt_len
= nla_get_u16(iter
);
6300 if (ip_pkt_len
> MKEEP_ALIVE_IP_PKT_MAX
) {
6305 case MKEEP_ALIVE_ATTRIBUTE_IP_PKT
:
6308 WL_ERR(("ip_pkt already allocated\n"));
6313 WL_ERR(("ip packet length is 0\n"));
6316 ip_pkt
= (u8
*)MALLOCZ(cfg
->osh
, ip_pkt_len
);
6317 if (ip_pkt
== NULL
) {
6319 WL_ERR(("Failed to allocate mem for ip packet\n"));
6322 memcpy(ip_pkt
, (u8
*)nla_data(iter
), ip_pkt_len
);
6324 case MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR
:
6325 memcpy(src_mac
, nla_data(iter
), ETHER_ADDR_LEN
);
6327 case MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR
:
6328 memcpy(dst_mac
, nla_data(iter
), ETHER_ADDR_LEN
);
6330 case MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC
:
6331 period_msec
= nla_get_u32(iter
);
6334 WL_ERR(("Unknown type: %d\n", type
));
6340 if (ip_pkt
== NULL
) {
6342 WL_ERR(("ip packet is NULL\n"));
6346 ret
= dhd_dev_start_mkeep_alive(dhd_pub
, mkeep_alive_id
, ip_pkt
, ip_pkt_len
, src_mac
,
6347 dst_mac
, period_msec
);
6349 WL_ERR(("start_mkeep_alive is failed ret: %d\n", ret
));
6354 MFREE(cfg
->osh
, ip_pkt
, ip_pkt_len
);
6360 static int wl_cfgvendor_stop_mkeep_alive(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
6361 const void *data
, int len
)
6363 int ret
= BCME_OK
, rem
, type
;
6364 uint8 mkeep_alive_id
= 0;
6365 const struct nlattr
*iter
;
6366 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6367 dhd_pub_t
*dhd_pub
= cfg
->pub
;
6369 nla_for_each_attr(iter
, data
, len
, rem
) {
6370 type
= nla_type(iter
);
6372 case MKEEP_ALIVE_ATTRIBUTE_ID
:
6373 mkeep_alive_id
= nla_get_u8(iter
);
6376 WL_ERR(("Unknown type: %d\n", type
));
6382 ret
= dhd_dev_stop_mkeep_alive(dhd_pub
, mkeep_alive_id
);
6384 WL_ERR(("stop_mkeep_alive is failed ret: %d\n", ret
));
6389 #endif /* KEEP_ALIVE */
6391 #if defined(PKT_FILTER_SUPPORT) && defined(APF)
6393 wl_cfgvendor_apf_get_capabilities(struct wiphy
*wiphy
,
6394 struct wireless_dev
*wdev
, const void *data
, int len
)
6396 struct net_device
*ndev
= wdev_to_ndev(wdev
);
6397 struct sk_buff
*skb
;
6398 int ret
, ver
, max_len
, mem_needed
;
6402 ret
= dhd_dev_apf_get_version(ndev
, &ver
);
6403 if (unlikely(ret
)) {
6404 WL_ERR(("APF get version failed, ret=%d\n", ret
));
6408 /* APF memory size limit */
6410 ret
= dhd_dev_apf_get_max_len(ndev
, &max_len
);
6411 if (unlikely(ret
)) {
6412 WL_ERR(("APF get maximum length failed, ret=%d\n", ret
));
6416 mem_needed
= VENDOR_REPLY_OVERHEAD
+ (ATTRIBUTE_U32_LEN
* 2);
6418 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, mem_needed
);
6419 if (unlikely(!skb
)) {
6420 WL_ERR(("%s: can't allocate %d bytes\n", __FUNCTION__
, mem_needed
));
6424 nla_put_u32(skb
, APF_ATTRIBUTE_VERSION
, ver
);
6425 nla_put_u32(skb
, APF_ATTRIBUTE_MAX_LEN
, max_len
);
6427 ret
= cfg80211_vendor_cmd_reply(skb
);
6428 if (unlikely(ret
)) {
6429 WL_ERR(("vendor command reply failed, ret=%d\n", ret
));
6436 wl_cfgvendor_apf_set_filter(struct wiphy
*wiphy
,
6437 struct wireless_dev
*wdev
, const void *data
, int len
)
6439 struct net_device
*ndev
= wdev_to_ndev(wdev
);
6440 const struct nlattr
*iter
;
6442 u32 program_len
= 0;
6444 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6447 WL_ERR(("Invalid len: %d\n", len
));
6451 nla_for_each_attr(iter
, data
, len
, tmp
) {
6452 type
= nla_type(iter
);
6454 case APF_ATTRIBUTE_PROGRAM_LEN
:
6455 /* check if the iter value is valid and program_len
6456 * is not already initialized.
6458 if (nla_len(iter
) == sizeof(uint32
) && !program_len
) {
6459 program_len
= nla_get_u32(iter
);
6465 if (program_len
> WL_APF_PROGRAM_MAX_SIZE
) {
6466 WL_ERR(("program len is more than expected len\n"));
6471 if (unlikely(!program_len
)) {
6472 WL_ERR(("zero program length\n"));
6477 case APF_ATTRIBUTE_PROGRAM
:
6478 if (unlikely(program
)) {
6479 WL_ERR(("program already allocated\n"));
6483 if (unlikely(!program_len
)) {
6484 WL_ERR(("program len is not set\n"));
6488 if (nla_len(iter
) != program_len
) {
6489 WL_ERR(("program_len is not same\n"));
6493 program
= MALLOCZ(cfg
->osh
, program_len
);
6494 if (unlikely(!program
)) {
6495 WL_ERR(("%s: can't allocate %d bytes\n",
6496 __FUNCTION__
, program_len
));
6500 memcpy(program
, (u8
*)nla_data(iter
), program_len
);
6503 WL_ERR(("%s: no such attribute %d\n", __FUNCTION__
, type
));
6509 ret
= dhd_dev_apf_add_filter(ndev
, program
, program_len
);
6513 MFREE(cfg
->osh
, program
, program_len
);
6517 #endif /* PKT_FILTER_SUPPORT && APF */
6519 #ifdef NDO_CONFIG_SUPPORT
6520 static int wl_cfgvendor_configure_nd_offload(struct wiphy
*wiphy
,
6521 struct wireless_dev
*wdev
, const void *data
, int len
)
6523 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6524 const struct nlattr
*iter
;
6525 int ret
= BCME_OK
, rem
, type
;
6528 nla_for_each_attr(iter
, data
, len
, rem
) {
6529 type
= nla_type(iter
);
6531 case ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE
:
6532 enable
= nla_get_u8(iter
);
6535 WL_ERR(("Unknown type: %d\n", type
));
6541 ret
= dhd_dev_ndo_cfg(bcmcfg_to_prmry_ndev(cfg
), enable
);
6543 WL_ERR(("dhd_dev_ndo_cfg() failed: %d\n", ret
));
6549 #endif /* NDO_CONFIG_SUPPORT */
6551 static const struct wiphy_vendor_command wl_vendor_cmds
[] = {
6554 .vendor_id
= OUI_BRCM
,
6555 .subcmd
= BRCM_VENDOR_SCMD_PRIV_STR
6557 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6558 .doit
= wl_cfgvendor_priv_string_handler
6560 #ifdef BCM_PRIV_CMD_SUPPORT
6563 .vendor_id
= OUI_BRCM
,
6564 .subcmd
= BRCM_VENDOR_SCMD_BCM_STR
6566 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6567 .doit
= wl_cfgvendor_priv_bcm_handler
6569 #endif /* BCM_PRIV_CMD_SUPPORT */
6570 #ifdef GSCAN_SUPPORT
6573 .vendor_id
= OUI_GOOGLE
,
6574 .subcmd
= GSCAN_SUBCMD_GET_CAPABILITIES
6576 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6577 .doit
= wl_cfgvendor_gscan_get_capabilities
6581 .vendor_id
= OUI_GOOGLE
,
6582 .subcmd
= GSCAN_SUBCMD_SET_CONFIG
6584 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6585 .doit
= wl_cfgvendor_set_scan_cfg
6589 .vendor_id
= OUI_GOOGLE
,
6590 .subcmd
= GSCAN_SUBCMD_SET_SCAN_CONFIG
6592 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6593 .doit
= wl_cfgvendor_set_batch_scan_cfg
6597 .vendor_id
= OUI_GOOGLE
,
6598 .subcmd
= GSCAN_SUBCMD_ENABLE_GSCAN
6600 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6601 .doit
= wl_cfgvendor_initiate_gscan
6605 .vendor_id
= OUI_GOOGLE
,
6606 .subcmd
= GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS
6608 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6609 .doit
= wl_cfgvendor_enable_full_scan_result
6613 .vendor_id
= OUI_GOOGLE
,
6614 .subcmd
= GSCAN_SUBCMD_SET_HOTLIST
6616 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6617 .doit
= wl_cfgvendor_hotlist_cfg
6621 .vendor_id
= OUI_GOOGLE
,
6622 .subcmd
= GSCAN_SUBCMD_GET_SCAN_RESULTS
6624 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6625 .doit
= wl_cfgvendor_gscan_get_batch_results
6627 #endif /* GSCAN_SUPPORT */
6628 #if defined(GSCAN_SUPPORT) || defined(DHD_GET_VALID_CHANNELS)
6631 .vendor_id
= OUI_GOOGLE
,
6632 .subcmd
= GSCAN_SUBCMD_GET_CHANNEL_LIST
6634 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6635 .doit
= wl_cfgvendor_gscan_get_channel_list
6637 #endif /* GSCAN_SUPPORT || DHD_GET_VALID_CHANNELS */
6641 .vendor_id
= OUI_GOOGLE
,
6642 .subcmd
= RTT_SUBCMD_SET_CONFIG
6644 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6645 .doit
= wl_cfgvendor_rtt_set_config
6649 .vendor_id
= OUI_GOOGLE
,
6650 .subcmd
= RTT_SUBCMD_CANCEL_CONFIG
6652 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6653 .doit
= wl_cfgvendor_rtt_cancel_config
6657 .vendor_id
= OUI_GOOGLE
,
6658 .subcmd
= RTT_SUBCMD_GETCAPABILITY
6660 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6661 .doit
= wl_cfgvendor_rtt_get_capability
6665 .vendor_id
= OUI_GOOGLE
,
6666 .subcmd
= RTT_SUBCMD_GETAVAILCHANNEL
6668 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6669 .doit
= wl_cfgvendor_rtt_get_responder_info
6673 .vendor_id
= OUI_GOOGLE
,
6674 .subcmd
= RTT_SUBCMD_SET_RESPONDER
6676 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6677 .doit
= wl_cfgvendor_rtt_set_responder
6681 .vendor_id
= OUI_GOOGLE
,
6682 .subcmd
= RTT_SUBCMD_CANCEL_RESPONDER
6684 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6685 .doit
= wl_cfgvendor_rtt_cancel_responder
6687 #endif /* RTT_SUPPORT */
6690 .vendor_id
= OUI_GOOGLE
,
6691 .subcmd
= ANDR_WIFI_SUBCMD_GET_FEATURE_SET
6693 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6694 .doit
= wl_cfgvendor_get_feature_set
6698 .vendor_id
= OUI_GOOGLE
,
6699 .subcmd
= ANDR_WIFI_SUBCMD_GET_FEATURE_SET_MATRIX
6701 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6702 .doit
= wl_cfgvendor_get_feature_set_matrix
6706 .vendor_id
= OUI_GOOGLE
,
6707 .subcmd
= ANDR_WIFI_RANDOM_MAC_OUI
6709 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6710 .doit
= wl_cfgvendor_set_rand_mac_oui
6712 #ifdef CUSTOM_FORCE_NODFS_FLAG
6715 .vendor_id
= OUI_GOOGLE
,
6716 .subcmd
= ANDR_WIFI_NODFS_CHANNELS
6718 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6719 .doit
= wl_cfgvendor_set_nodfs_flag
6721 #endif /* CUSTOM_FORCE_NODFS_FLAG */
6724 .vendor_id
= OUI_GOOGLE
,
6725 .subcmd
= ANDR_WIFI_SET_COUNTRY
6727 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6728 .doit
= wl_cfgvendor_set_country
6730 #ifdef LINKSTAT_SUPPORT
6733 .vendor_id
= OUI_GOOGLE
,
6734 .subcmd
= LSTATS_SUBCMD_GET_INFO
6736 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6737 .doit
= wl_cfgvendor_lstats_get_info
6739 #endif /* LINKSTAT_SUPPORT */
6741 #ifdef GSCAN_SUPPORT
6744 .vendor_id
= OUI_GOOGLE
,
6745 .subcmd
= GSCAN_SUBCMD_SET_EPNO_SSID
6747 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6748 .doit
= wl_cfgvendor_epno_cfg
6753 .vendor_id
= OUI_GOOGLE
,
6754 .subcmd
= WIFI_SUBCMD_SET_LAZY_ROAM_PARAMS
6756 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6757 .doit
= wl_cfgvendor_set_lazy_roam_cfg
6762 .vendor_id
= OUI_GOOGLE
,
6763 .subcmd
= WIFI_SUBCMD_ENABLE_LAZY_ROAM
6765 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6766 .doit
= wl_cfgvendor_enable_lazy_roam
6771 .vendor_id
= OUI_GOOGLE
,
6772 .subcmd
= WIFI_SUBCMD_SET_BSSID_PREF
6774 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6775 .doit
= wl_cfgvendor_set_bssid_pref
6778 #endif /* GSCAN_SUPPORT */
6779 #if defined(GSCAN_SUPPORT) || defined(ROAMEXP_SUPPORT)
6782 .vendor_id
= OUI_GOOGLE
,
6783 .subcmd
= WIFI_SUBCMD_SET_SSID_WHITELIST
6785 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6786 .doit
= wl_cfgvendor_set_ssid_whitelist
6791 .vendor_id
= OUI_GOOGLE
,
6792 .subcmd
= WIFI_SUBCMD_SET_BSSID_BLACKLIST
6794 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6795 .doit
= wl_cfgvendor_set_bssid_blacklist
6797 #endif /* GSCAN_SUPPORT || ROAMEXP_SUPPORT */
6798 #ifdef ROAMEXP_SUPPORT
6801 .vendor_id
= OUI_GOOGLE
,
6802 .subcmd
= WIFI_SUBCMD_FW_ROAM_POLICY
6804 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6805 .doit
= wl_cfgvendor_set_fw_roaming_state
6809 .vendor_id
= OUI_GOOGLE
,
6810 .subcmd
= WIFI_SUBCMD_ROAM_CAPABILITY
6812 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6813 .doit
= wl_cfgvendor_fw_roam_get_capability
6815 #endif /* ROAMEXP_SUPPORT */
6818 .vendor_id
= OUI_GOOGLE
,
6819 .subcmd
= DEBUG_GET_VER
6821 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6822 .doit
= wl_cfgvendor_dbg_get_version
6827 .vendor_id
= OUI_GOOGLE
,
6828 .subcmd
= DEBUG_START_LOGGING
6830 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6831 .doit
= wl_cfgvendor_dbg_start_logging
6835 .vendor_id
= OUI_GOOGLE
,
6836 .subcmd
= DEBUG_RESET_LOGGING
6838 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6839 .doit
= wl_cfgvendor_dbg_reset_logging
6843 .vendor_id
= OUI_GOOGLE
,
6844 .subcmd
= DEBUG_TRIGGER_MEM_DUMP
6846 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6847 .doit
= wl_cfgvendor_dbg_trigger_mem_dump
6851 .vendor_id
= OUI_GOOGLE
,
6852 .subcmd
= DEBUG_GET_MEM_DUMP
6854 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6855 .doit
= wl_cfgvendor_dbg_get_mem_dump
6859 .vendor_id
= OUI_GOOGLE
,
6860 .subcmd
= DEBUG_GET_RING_STATUS
6862 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6863 .doit
= wl_cfgvendor_dbg_get_ring_status
6867 .vendor_id
= OUI_GOOGLE
,
6868 .subcmd
= DEBUG_GET_RING_DATA
6870 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6871 .doit
= wl_cfgvendor_dbg_get_ring_data
6873 #endif /* DEBUGABILITY */
6876 .vendor_id
= OUI_GOOGLE
,
6877 .subcmd
= DEBUG_GET_FEATURE
6879 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6880 .doit
= wl_cfgvendor_dbg_get_feature
6885 .vendor_id
= OUI_GOOGLE
,
6886 .subcmd
= DEBUG_START_PKT_FATE_MONITORING
6888 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6889 .doit
= wl_cfgvendor_dbg_start_pkt_fate_monitoring
6893 .vendor_id
= OUI_GOOGLE
,
6894 .subcmd
= DEBUG_GET_TX_PKT_FATES
6896 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6897 .doit
= wl_cfgvendor_dbg_get_tx_pkt_fates
6901 .vendor_id
= OUI_GOOGLE
,
6902 .subcmd
= DEBUG_GET_RX_PKT_FATES
6904 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6905 .doit
= wl_cfgvendor_dbg_get_rx_pkt_fates
6907 #endif /* DBG_PKT_MON */
6911 .vendor_id
= OUI_GOOGLE
,
6912 .subcmd
= WIFI_OFFLOAD_SUBCMD_START_MKEEP_ALIVE
6914 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6915 .doit
= wl_cfgvendor_start_mkeep_alive
6919 .vendor_id
= OUI_GOOGLE
,
6920 .subcmd
= WIFI_OFFLOAD_SUBCMD_STOP_MKEEP_ALIVE
6922 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6923 .doit
= wl_cfgvendor_stop_mkeep_alive
6925 #endif /* KEEP_ALIVE */
6929 .vendor_id
= OUI_GOOGLE
,
6930 .subcmd
= NAN_WIFI_SUBCMD_ENABLE
6932 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6933 .doit
= wl_cfgvendor_nan_start_handler
6937 .vendor_id
= OUI_GOOGLE
,
6938 .subcmd
= NAN_WIFI_SUBCMD_DISABLE
6940 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6941 .doit
= wl_cfgvendor_nan_stop_handler
6945 .vendor_id
= OUI_GOOGLE
,
6946 .subcmd
= NAN_WIFI_SUBCMD_CONFIG
6948 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6949 .doit
= wl_cfgvendor_nan_config_handler
6953 .vendor_id
= OUI_GOOGLE
,
6954 .subcmd
= NAN_WIFI_SUBCMD_REQUEST_PUBLISH
6956 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6957 .doit
= wl_cfgvendor_nan_req_publish
6961 .vendor_id
= OUI_GOOGLE
,
6962 .subcmd
= NAN_WIFI_SUBCMD_REQUEST_SUBSCRIBE
6964 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6965 .doit
= wl_cfgvendor_nan_req_subscribe
6969 .vendor_id
= OUI_GOOGLE
,
6970 .subcmd
= NAN_WIFI_SUBCMD_CANCEL_PUBLISH
6972 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6973 .doit
= wl_cfgvendor_nan_cancel_publish
6977 .vendor_id
= OUI_GOOGLE
,
6978 .subcmd
= NAN_WIFI_SUBCMD_CANCEL_SUBSCRIBE
6980 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6981 .doit
= wl_cfgvendor_nan_cancel_subscribe
6985 .vendor_id
= OUI_GOOGLE
,
6986 .subcmd
= NAN_WIFI_SUBCMD_TRANSMIT
6988 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6989 .doit
= wl_cfgvendor_nan_transmit
6993 .vendor_id
= OUI_GOOGLE
,
6994 .subcmd
= NAN_WIFI_SUBCMD_GET_CAPABILITIES
6996 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
6997 .doit
= wl_cfgvendor_nan_get_capablities
7002 .vendor_id
= OUI_GOOGLE
,
7003 .subcmd
= NAN_WIFI_SUBCMD_DATA_PATH_IFACE_CREATE
7005 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7006 .doit
= wl_cfgvendor_nan_data_path_iface_create
7010 .vendor_id
= OUI_GOOGLE
,
7011 .subcmd
= NAN_WIFI_SUBCMD_DATA_PATH_IFACE_DELETE
7013 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7014 .doit
= wl_cfgvendor_nan_data_path_iface_delete
7018 .vendor_id
= OUI_GOOGLE
,
7019 .subcmd
= NAN_WIFI_SUBCMD_DATA_PATH_REQUEST
7021 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7022 .doit
= wl_cfgvendor_nan_data_path_request
7026 .vendor_id
= OUI_GOOGLE
,
7027 .subcmd
= NAN_WIFI_SUBCMD_DATA_PATH_RESPONSE
7029 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7030 .doit
= wl_cfgvendor_nan_data_path_response
7034 .vendor_id
= OUI_GOOGLE
,
7035 .subcmd
= NAN_WIFI_SUBCMD_DATA_PATH_END
7037 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7038 .doit
= wl_cfgvendor_nan_data_path_end
7040 #ifdef WL_NAN_DISC_CACHE
7043 .vendor_id
= OUI_GOOGLE
,
7044 .subcmd
= NAN_WIFI_SUBCMD_DATA_PATH_SEC_INFO
7046 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7047 .doit
= wl_cfgvendor_nan_data_path_sec_info
7049 #endif /* WL_NAN_DISC_CACHE */
7052 .vendor_id
= OUI_GOOGLE
,
7053 .subcmd
= NAN_WIFI_SUBCMD_VERSION_INFO
7055 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7056 .doit
= wl_cfgvendor_nan_version_info
7059 #if defined(PKT_FILTER_SUPPORT) && defined(APF)
7062 .vendor_id
= OUI_GOOGLE
,
7063 .subcmd
= APF_SUBCMD_GET_CAPABILITIES
7065 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7066 .doit
= wl_cfgvendor_apf_get_capabilities
7071 .vendor_id
= OUI_GOOGLE
,
7072 .subcmd
= APF_SUBCMD_SET_FILTER
7074 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7075 .doit
= wl_cfgvendor_apf_set_filter
7077 #endif /* PKT_FILTER_SUPPORT && APF */
7078 #ifdef NDO_CONFIG_SUPPORT
7081 .vendor_id
= OUI_GOOGLE
,
7082 .subcmd
= WIFI_SUBCMD_CONFIG_ND_OFFLOAD
7084 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7085 .doit
= wl_cfgvendor_configure_nd_offload
7087 #endif /* NDO_CONFIG_SUPPORT */
7088 #ifdef RSSI_MONITOR_SUPPORT
7091 .vendor_id
= OUI_GOOGLE
,
7092 .subcmd
= WIFI_SUBCMD_SET_RSSI_MONITOR
7094 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7095 .doit
= wl_cfgvendor_set_rssi_monitor
7097 #endif /* RSSI_MONITOR_SUPPORT */
7098 #ifdef DHDTCPACK_SUPPRESS
7101 .vendor_id
= OUI_GOOGLE
,
7102 .subcmd
= WIFI_SUBCMD_CONFIG_TCPACK_SUP
7104 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7105 .doit
= wl_cfgvendor_set_tcpack_sup_mode
7107 #endif /* DHDTCPACK_SUPPRESS */
7108 #ifdef DHD_WAKE_STATUS
7111 .vendor_id
= OUI_GOOGLE
,
7112 .subcmd
= DEBUG_GET_WAKE_REASON_STATS
7114 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
| WIPHY_VENDOR_CMD_NEED_NETDEV
,
7115 .doit
= wl_cfgvendor_get_wake_reason_stats
7117 #endif /* DHD_WAKE_STATUS */
7120 static const struct nl80211_vendor_cmd_info wl_vendor_events
[] = {
7121 { OUI_BRCM
, BRCM_VENDOR_EVENT_UNSPEC
},
7122 { OUI_BRCM
, BRCM_VENDOR_EVENT_PRIV_STR
},
7123 { OUI_GOOGLE
, GOOGLE_GSCAN_SIGNIFICANT_EVENT
},
7124 { OUI_GOOGLE
, GOOGLE_GSCAN_GEOFENCE_FOUND_EVENT
},
7125 { OUI_GOOGLE
, GOOGLE_GSCAN_BATCH_SCAN_EVENT
},
7126 { OUI_GOOGLE
, GOOGLE_SCAN_FULL_RESULTS_EVENT
},
7127 { OUI_GOOGLE
, GOOGLE_RTT_COMPLETE_EVENT
},
7128 { OUI_GOOGLE
, GOOGLE_SCAN_COMPLETE_EVENT
},
7129 { OUI_GOOGLE
, GOOGLE_GSCAN_GEOFENCE_LOST_EVENT
},
7130 { OUI_GOOGLE
, GOOGLE_SCAN_EPNO_EVENT
},
7131 { OUI_GOOGLE
, GOOGLE_DEBUG_RING_EVENT
},
7132 { OUI_GOOGLE
, GOOGLE_FW_DUMP_EVENT
},
7133 { OUI_GOOGLE
, GOOGLE_PNO_HOTSPOT_FOUND_EVENT
},
7134 { OUI_GOOGLE
, GOOGLE_RSSI_MONITOR_EVENT
},
7135 { OUI_GOOGLE
, GOOGLE_MKEEP_ALIVE_EVENT
},
7136 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_ENABLED
},
7137 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_DISABLED
},
7138 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_SUBSCRIBE_MATCH
},
7139 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_REPLIED
},
7140 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_PUBLISH_TERMINATED
},
7141 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_SUBSCRIBE_TERMINATED
},
7142 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_DE_EVENT
},
7143 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_FOLLOWUP
},
7144 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_TRANSMIT_FOLLOWUP_IND
},
7145 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_DATA_REQUEST
},
7146 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_DATA_CONFIRMATION
},
7147 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_DATA_END
},
7148 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_BEACON
},
7149 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_SDF
},
7150 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_TCA
},
7151 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_SUBSCRIBE_UNMATCH
},
7152 { OUI_GOOGLE
, GOOGLE_NAN_EVENT_UNKNOWN
},
7153 { OUI_GOOGLE
, GOOGLE_ROAM_EVENT_START
},
7154 { OUI_BRCM
, BRCM_VENDOR_EVENT_HANGED
}
7157 int wl_cfgvendor_attach(struct wiphy
*wiphy
, dhd_pub_t
*dhd
)
7160 WL_INFORM_MEM(("Vendor: Register BRCM cfg80211 vendor cmd(0x%x) interface \n",
7161 NL80211_CMD_VENDOR
));
7163 wiphy
->vendor_commands
= wl_vendor_cmds
;
7164 wiphy
->n_vendor_commands
= ARRAY_SIZE(wl_vendor_cmds
);
7165 wiphy
->vendor_events
= wl_vendor_events
;
7166 wiphy
->n_vendor_events
= ARRAY_SIZE(wl_vendor_events
);
7169 dhd_os_dbg_register_callback(FW_VERBOSE_RING_ID
, wl_cfgvendor_dbg_ring_send_evt
);
7170 dhd_os_dbg_register_callback(FW_EVENT_RING_ID
, wl_cfgvendor_dbg_ring_send_evt
);
7171 dhd_os_dbg_register_callback(DHD_EVENT_RING_ID
, wl_cfgvendor_dbg_ring_send_evt
);
7172 dhd_os_dbg_register_callback(NAN_EVENT_RING_ID
, wl_cfgvendor_dbg_ring_send_evt
);
7173 dhd_os_dbg_register_urgent_notifier(dhd
, wl_cfgvendor_dbg_send_urgent_evt
);
7174 #endif /* DEBUGABILITY */
7179 int wl_cfgvendor_detach(struct wiphy
*wiphy
)
7181 WL_INFORM_MEM(("Vendor: Unregister BRCM cfg80211 vendor interface \n"));
7183 wiphy
->vendor_commands
= NULL
;
7184 wiphy
->vendor_events
= NULL
;
7185 wiphy
->n_vendor_commands
= 0;
7186 wiphy
->n_vendor_events
= 0;
7190 #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */