Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
nu11secur1ty
GitHub Repository: nu11secur1ty/Kali-Linux
Path: blob/master/ALFA-W1F1/RTL8814AU/os_dep/linux/rtw_cfgvendor.c
1307 views
1
/******************************************************************************
2
*
3
* Copyright(c) 2007 - 2017 Realtek Corporation.
4
*
5
* This program is free software; you can redistribute it and/or modify it
6
* under the terms of version 2 of the GNU General Public License as
7
* published by the Free Software Foundation.
8
*
9
* This program is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12
* more details.
13
*
14
*****************************************************************************/
15
16
#include <drv_types.h>
17
18
#ifdef CONFIG_IOCTL_CFG80211
19
20
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(RTW_VENDOR_EXT_SUPPORT)
21
22
/*
23
#include <linux/kernel.h>
24
#include <linux/if_arp.h>
25
#include <asm/uaccess.h>
26
27
#include <linux/kernel.h>
28
#include <linux/kthread.h>
29
#include <linux/netdevice.h>
30
#include <linux/sched.h>
31
#include <linux/etherdevice.h>
32
#include <linux/wireless.h>
33
#include <linux/ieee80211.h>
34
#include <linux/wait.h>
35
#include <net/cfg80211.h>
36
*/
37
38
#include <net/rtnetlink.h>
39
40
#ifdef DBG_MEM_ALLOC
41
extern bool match_mstat_sniff_rules(const enum mstat_f flags, const size_t size);
42
struct sk_buff *dbg_rtw_cfg80211_vendor_event_alloc(struct wiphy *wiphy, struct wireless_dev *wdev, int len, int event_id, gfp_t gfp
43
, const enum mstat_f flags, const char *func, const int line)
44
{
45
struct sk_buff *skb;
46
unsigned int truesize = 0;
47
48
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0))
49
skb = cfg80211_vendor_event_alloc(wiphy, len, event_id, gfp);
50
#else
51
skb = cfg80211_vendor_event_alloc(wiphy, wdev, len, event_id, gfp);
52
#endif
53
54
if (skb)
55
truesize = skb->truesize;
56
57
if (!skb || truesize < len || match_mstat_sniff_rules(flags, truesize))
58
RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%d), skb:%p, truesize=%u\n", func, line, __FUNCTION__, len, skb, truesize);
59
60
rtw_mstat_update(
61
flags
62
, skb ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL
63
, truesize
64
);
65
66
return skb;
67
}
68
69
void dbg_rtw_cfg80211_vendor_event(struct sk_buff *skb, gfp_t gfp
70
, const enum mstat_f flags, const char *func, const int line)
71
{
72
unsigned int truesize = skb->truesize;
73
74
if (match_mstat_sniff_rules(flags, truesize))
75
RTW_INFO("DBG_MEM_ALLOC %s:%d %s, truesize=%u\n", func, line, __FUNCTION__, truesize);
76
77
cfg80211_vendor_event(skb, gfp);
78
79
rtw_mstat_update(
80
flags
81
, MSTAT_FREE
82
, truesize
83
);
84
}
85
86
struct sk_buff *dbg_rtw_cfg80211_vendor_cmd_alloc_reply_skb(struct wiphy *wiphy, int len
87
, const enum mstat_f flags, const char *func, const int line)
88
{
89
struct sk_buff *skb;
90
unsigned int truesize = 0;
91
92
skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len);
93
94
if (skb)
95
truesize = skb->truesize;
96
97
if (!skb || truesize < len || match_mstat_sniff_rules(flags, truesize))
98
RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%d), skb:%p, truesize=%u\n", func, line, __FUNCTION__, len, skb, truesize);
99
100
rtw_mstat_update(
101
flags
102
, skb ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL
103
, truesize
104
);
105
106
return skb;
107
}
108
109
int dbg_rtw_cfg80211_vendor_cmd_reply(struct sk_buff *skb
110
, const enum mstat_f flags, const char *func, const int line)
111
{
112
unsigned int truesize = skb->truesize;
113
int ret;
114
115
if (match_mstat_sniff_rules(flags, truesize))
116
RTW_INFO("DBG_MEM_ALLOC %s:%d %s, truesize=%u\n", func, line, __FUNCTION__, truesize);
117
118
ret = cfg80211_vendor_cmd_reply(skb);
119
120
rtw_mstat_update(
121
flags
122
, MSTAT_FREE
123
, truesize
124
);
125
126
return ret;
127
}
128
129
#define rtw_cfg80211_vendor_event_alloc(wiphy, wdev, len, event_id, gfp) \
130
dbg_rtw_cfg80211_vendor_event_alloc(wiphy, wdev, len, event_id, gfp, MSTAT_FUNC_CFG_VENDOR | MSTAT_TYPE_SKB, __FUNCTION__, __LINE__)
131
132
#define rtw_cfg80211_vendor_event(skb, gfp) \
133
dbg_rtw_cfg80211_vendor_event(skb, gfp, MSTAT_FUNC_CFG_VENDOR | MSTAT_TYPE_SKB, __FUNCTION__, __LINE__)
134
135
#define rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len) \
136
dbg_rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len, MSTAT_FUNC_CFG_VENDOR | MSTAT_TYPE_SKB, __FUNCTION__, __LINE__)
137
138
#define rtw_cfg80211_vendor_cmd_reply(skb) \
139
dbg_rtw_cfg80211_vendor_cmd_reply(skb, MSTAT_FUNC_CFG_VENDOR | MSTAT_TYPE_SKB, __FUNCTION__, __LINE__)
140
#else
141
142
struct sk_buff *rtw_cfg80211_vendor_event_alloc(
143
struct wiphy *wiphy, struct wireless_dev *wdev, int len, int event_id, gfp_t gfp)
144
{
145
struct sk_buff *skb;
146
147
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0))
148
skb = cfg80211_vendor_event_alloc(wiphy, len, event_id, gfp);
149
#else
150
skb = cfg80211_vendor_event_alloc(wiphy, wdev, len, event_id, gfp);
151
#endif
152
return skb;
153
}
154
155
#define rtw_cfg80211_vendor_event(skb, gfp) \
156
cfg80211_vendor_event(skb, gfp)
157
158
#define rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len) \
159
cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len)
160
161
#define rtw_cfg80211_vendor_cmd_reply(skb) \
162
cfg80211_vendor_cmd_reply(skb)
163
#endif /* DBG_MEM_ALLOC */
164
165
/*
166
* This API is to be used for asynchronous vendor events. This
167
* shouldn't be used in response to a vendor command from its
168
* do_it handler context (instead rtw_cfgvendor_send_cmd_reply should
169
* be used).
170
*/
171
int rtw_cfgvendor_send_async_event(struct wiphy *wiphy,
172
struct net_device *dev, int event_id, const void *data, int len)
173
{
174
u16 kflags;
175
struct sk_buff *skb;
176
177
kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
178
179
/* Alloc the SKB for vendor_event */
180
skb = rtw_cfg80211_vendor_event_alloc(wiphy, ndev_to_wdev(dev), len, event_id, kflags);
181
if (!skb) {
182
RTW_ERR(FUNC_NDEV_FMT" skb alloc failed", FUNC_NDEV_ARG(dev));
183
return -ENOMEM;
184
}
185
186
/* Push the data to the skb */
187
nla_put_nohdr(skb, len, data);
188
189
rtw_cfg80211_vendor_event(skb, kflags);
190
191
return 0;
192
}
193
194
static int rtw_cfgvendor_send_cmd_reply(struct wiphy *wiphy,
195
struct net_device *dev, const void *data, int len)
196
{
197
struct sk_buff *skb;
198
199
/* Alloc the SKB for vendor_event */
200
skb = rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len);
201
if (unlikely(!skb)) {
202
RTW_ERR(FUNC_NDEV_FMT" skb alloc failed", FUNC_NDEV_ARG(dev));
203
return -ENOMEM;
204
}
205
206
/* Push the data to the skb */
207
nla_put_nohdr(skb, len, data);
208
209
return rtw_cfg80211_vendor_cmd_reply(skb);
210
}
211
212
/* Feature enums */
213
#define WIFI_FEATURE_INFRA 0x0001 // Basic infrastructure mode
214
#define WIFI_FEATURE_INFRA_5G 0x0002 // Support for 5 GHz Band
215
#define WIFI_FEATURE_HOTSPOT 0x0004 // Support for GAS/ANQP
216
#define WIFI_FEATURE_P2P 0x0008 // Wifi-Direct
217
#define WIFI_FEATURE_SOFT_AP 0x0010 // Soft AP
218
#define WIFI_FEATURE_GSCAN 0x0020 // Google-Scan APIs
219
#define WIFI_FEATURE_NAN 0x0040 // Neighbor Awareness Networking
220
#define WIFI_FEATURE_D2D_RTT 0x0080 // Device-to-device RTT
221
#define WIFI_FEATURE_D2AP_RTT 0x0100 // Device-to-AP RTT
222
#define WIFI_FEATURE_BATCH_SCAN 0x0200 // Batched Scan (legacy)
223
#define WIFI_FEATURE_PNO 0x0400 // Preferred network offload
224
#define WIFI_FEATURE_ADDITIONAL_STA 0x0800 // Support for two STAs
225
#define WIFI_FEATURE_TDLS 0x1000 // Tunnel directed link setup
226
#define WIFI_FEATURE_TDLS_OFFCHANNEL 0x2000 // Support for TDLS off channel
227
#define WIFI_FEATURE_EPR 0x4000 // Enhanced power reporting
228
#define WIFI_FEATURE_AP_STA 0x8000 // Support for AP STA Concurrency
229
#define WIFI_FEATURE_LINK_LAYER_STATS 0x10000 // Link layer stats collection
230
#define WIFI_FEATURE_LOGGER 0x20000 // WiFi Logger
231
#define WIFI_FEATURE_HAL_EPNO 0x40000 // WiFi PNO enhanced
232
#define WIFI_FEATURE_RSSI_MONITOR 0x80000 // RSSI Monitor
233
#define WIFI_FEATURE_MKEEP_ALIVE 0x100000 // WiFi mkeep_alive
234
#define WIFI_FEATURE_CONFIG_NDO 0x200000 // ND offload configure
235
#define WIFI_FEATURE_TX_TRANSMIT_POWER 0x400000 // Capture Tx transmit power levels
236
#define WIFI_FEATURE_CONTROL_ROAMING 0x800000 // Enable/Disable firmware roaming
237
#define WIFI_FEATURE_IE_WHITELIST 0x1000000 // Support Probe IE white listing
238
#define WIFI_FEATURE_SCAN_RAND 0x2000000 // Support MAC & Probe Sequence Number randomization
239
// Add more features here
240
241
#define MAX_FEATURE_SET_CONCURRRENT_GROUPS 3
242
243
#include <hal_data.h>
244
int rtw_dev_get_feature_set(struct net_device *dev)
245
{
246
_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
247
HAL_DATA_TYPE *HalData = GET_HAL_DATA(adapter);
248
int feature_set = 0;
249
250
feature_set |= WIFI_FEATURE_INFRA;
251
252
#ifdef CONFIG_IEEE80211_BAND_5GHZ
253
if (is_supported_5g(adapter_to_regsty(adapter)->wireless_mode))
254
feature_set |= WIFI_FEATURE_INFRA_5G;
255
#endif
256
257
feature_set |= WIFI_FEATURE_P2P;
258
feature_set |= WIFI_FEATURE_SOFT_AP;
259
260
feature_set |= WIFI_FEATURE_ADDITIONAL_STA;
261
#ifdef CONFIG_RTW_CFGVEDNOR_LLSTATS
262
feature_set |= WIFI_FEATURE_LINK_LAYER_STATS;
263
#endif /* CONFIG_RTW_CFGVEDNOR_LLSTATS */
264
265
#ifdef CONFIG_RTW_CFGVEDNOR_RSSIMONITOR
266
feature_set |= WIFI_FEATURE_RSSI_MONITOR;
267
#endif
268
269
#ifdef CONFIG_RTW_CFGVENDOR_WIFI_LOGGER
270
feature_set |= WIFI_FEATURE_LOGGER;
271
#endif
272
273
#ifdef CONFIG_RTW_WIFI_HAL
274
feature_set |= WIFI_FEATURE_CONFIG_NDO;
275
feature_set |= WIFI_FEATURE_SCAN_RAND;
276
#endif
277
278
return feature_set;
279
}
280
281
int *rtw_dev_get_feature_set_matrix(struct net_device *dev, int *num)
282
{
283
int feature_set_full, mem_needed;
284
int *ret;
285
286
*num = 0;
287
mem_needed = sizeof(int) * MAX_FEATURE_SET_CONCURRRENT_GROUPS;
288
ret = (int *)rtw_malloc(mem_needed);
289
290
if (!ret) {
291
RTW_ERR(FUNC_NDEV_FMT" failed to allocate %d bytes\n"
292
, FUNC_NDEV_ARG(dev), mem_needed);
293
return ret;
294
}
295
296
feature_set_full = rtw_dev_get_feature_set(dev);
297
298
ret[0] = (feature_set_full & WIFI_FEATURE_INFRA) |
299
(feature_set_full & WIFI_FEATURE_INFRA_5G) |
300
(feature_set_full & WIFI_FEATURE_NAN) |
301
(feature_set_full & WIFI_FEATURE_D2D_RTT) |
302
(feature_set_full & WIFI_FEATURE_D2AP_RTT) |
303
(feature_set_full & WIFI_FEATURE_PNO) |
304
(feature_set_full & WIFI_FEATURE_BATCH_SCAN) |
305
(feature_set_full & WIFI_FEATURE_GSCAN) |
306
(feature_set_full & WIFI_FEATURE_HOTSPOT) |
307
(feature_set_full & WIFI_FEATURE_ADDITIONAL_STA) |
308
(feature_set_full & WIFI_FEATURE_EPR);
309
310
ret[1] = (feature_set_full & WIFI_FEATURE_INFRA) |
311
(feature_set_full & WIFI_FEATURE_INFRA_5G) |
312
/* Not yet verified NAN with P2P */
313
/* (feature_set_full & WIFI_FEATURE_NAN) | */
314
(feature_set_full & WIFI_FEATURE_P2P) |
315
(feature_set_full & WIFI_FEATURE_D2AP_RTT) |
316
(feature_set_full & WIFI_FEATURE_D2D_RTT) |
317
(feature_set_full & WIFI_FEATURE_EPR);
318
319
ret[2] = (feature_set_full & WIFI_FEATURE_INFRA) |
320
(feature_set_full & WIFI_FEATURE_INFRA_5G) |
321
(feature_set_full & WIFI_FEATURE_NAN) |
322
(feature_set_full & WIFI_FEATURE_D2D_RTT) |
323
(feature_set_full & WIFI_FEATURE_D2AP_RTT) |
324
(feature_set_full & WIFI_FEATURE_TDLS) |
325
(feature_set_full & WIFI_FEATURE_TDLS_OFFCHANNEL) |
326
(feature_set_full & WIFI_FEATURE_EPR);
327
*num = MAX_FEATURE_SET_CONCURRRENT_GROUPS;
328
329
return ret;
330
}
331
332
static int rtw_cfgvendor_get_feature_set(struct wiphy *wiphy,
333
struct wireless_dev *wdev, const void *data, int len)
334
{
335
int err = 0;
336
int reply;
337
338
reply = rtw_dev_get_feature_set(wdev_to_ndev(wdev));
339
340
err = rtw_cfgvendor_send_cmd_reply(wiphy, wdev_to_ndev(wdev), &reply, sizeof(int));
341
342
if (unlikely(err))
343
RTW_ERR(FUNC_NDEV_FMT" Vendor Command reply failed ret:%d\n"
344
, FUNC_NDEV_ARG(wdev_to_ndev(wdev)), err);
345
346
return err;
347
}
348
349
static int rtw_cfgvendor_get_feature_set_matrix(struct wiphy *wiphy,
350
struct wireless_dev *wdev, const void *data, int len)
351
{
352
int err = 0;
353
struct sk_buff *skb;
354
int *reply;
355
int num, mem_needed, i;
356
357
reply = rtw_dev_get_feature_set_matrix(wdev_to_ndev(wdev), &num);
358
359
if (!reply) {
360
RTW_ERR(FUNC_NDEV_FMT" Could not get feature list matrix\n"
361
, FUNC_NDEV_ARG(wdev_to_ndev(wdev)));
362
err = -EINVAL;
363
return err;
364
}
365
366
mem_needed = VENDOR_REPLY_OVERHEAD + (ATTRIBUTE_U32_LEN * num) +
367
ATTRIBUTE_U32_LEN;
368
369
/* Alloc the SKB for vendor_event */
370
skb = rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);
371
if (unlikely(!skb)) {
372
RTW_ERR(FUNC_NDEV_FMT" skb alloc failed", FUNC_NDEV_ARG(wdev_to_ndev(wdev)));
373
err = -ENOMEM;
374
goto exit;
375
}
376
377
nla_put_u32(skb, ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, num);
378
for (i = 0; i < num; i++)
379
nla_put_u32(skb, ANDR_WIFI_ATTRIBUTE_FEATURE_SET, reply[i]);
380
381
err = rtw_cfg80211_vendor_cmd_reply(skb);
382
383
if (unlikely(err))
384
RTW_ERR(FUNC_NDEV_FMT" Vendor Command reply failed ret:%d\n"
385
, FUNC_NDEV_ARG(wdev_to_ndev(wdev)), err);
386
exit:
387
rtw_mfree((u8 *)reply, sizeof(int) * num);
388
return err;
389
}
390
391
#if defined(GSCAN_SUPPORT) && 0
392
int rtw_cfgvendor_send_hotlist_event(struct wiphy *wiphy,
393
struct net_device *dev, void *data, int len, rtw_vendor_event_t event)
394
{
395
u16 kflags;
396
const void *ptr;
397
struct sk_buff *skb;
398
int malloc_len, total, iter_cnt_to_send, cnt;
399
gscan_results_cache_t *cache = (gscan_results_cache_t *)data;
400
401
total = len / sizeof(wifi_gscan_result_t);
402
while (total > 0) {
403
malloc_len = (total * sizeof(wifi_gscan_result_t)) + VENDOR_DATA_OVERHEAD;
404
if (malloc_len > NLMSG_DEFAULT_SIZE)
405
malloc_len = NLMSG_DEFAULT_SIZE;
406
iter_cnt_to_send =
407
(malloc_len - VENDOR_DATA_OVERHEAD) / sizeof(wifi_gscan_result_t);
408
total = total - iter_cnt_to_send;
409
410
kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
411
412
/* Alloc the SKB for vendor_event */
413
skb = rtw_cfg80211_vendor_event_alloc(wiphy, ndev_to_wdev(dev), malloc_len, event, kflags);
414
if (!skb) {
415
WL_ERR(("skb alloc failed"));
416
return -ENOMEM;
417
}
418
419
while (cache && iter_cnt_to_send) {
420
ptr = (const void *) &cache->results[cache->tot_consumed];
421
422
if (iter_cnt_to_send < (cache->tot_count - cache->tot_consumed))
423
cnt = iter_cnt_to_send;
424
else
425
cnt = (cache->tot_count - cache->tot_consumed);
426
427
iter_cnt_to_send -= cnt;
428
cache->tot_consumed += cnt;
429
/* Push the data to the skb */
430
nla_append(skb, cnt * sizeof(wifi_gscan_result_t), ptr);
431
if (cache->tot_consumed == cache->tot_count)
432
cache = cache->next;
433
434
}
435
436
rtw_cfg80211_vendor_event(skb, kflags);
437
}
438
439
return 0;
440
}
441
442
443
static int rtw_cfgvendor_gscan_get_capabilities(struct wiphy *wiphy,
444
struct wireless_dev *wdev, const void *data, int len)
445
{
446
int err = 0;
447
struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
448
dhd_pno_gscan_capabilities_t *reply = NULL;
449
uint32 reply_len = 0;
450
451
452
reply = dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg),
453
DHD_PNO_GET_CAPABILITIES, NULL, &reply_len);
454
if (!reply) {
455
WL_ERR(("Could not get capabilities\n"));
456
err = -EINVAL;
457
return err;
458
}
459
460
err = rtw_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),
461
reply, reply_len);
462
463
if (unlikely(err))
464
WL_ERR(("Vendor Command reply failed ret:%d\n", err));
465
466
kfree(reply);
467
return err;
468
}
469
470
static int rtw_cfgvendor_gscan_get_channel_list(struct wiphy *wiphy,
471
struct wireless_dev *wdev, const void *data, int len)
472
{
473
int err = 0, type, band;
474
struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
475
uint16 *reply = NULL;
476
uint32 reply_len = 0, num_channels, mem_needed;
477
struct sk_buff *skb;
478
479
type = nla_type(data);
480
481
if (type == GSCAN_ATTRIBUTE_BAND)
482
band = nla_get_u32(data);
483
else
484
return -1;
485
486
reply = dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg),
487
DHD_PNO_GET_CHANNEL_LIST, &band, &reply_len);
488
489
if (!reply) {
490
WL_ERR(("Could not get channel list\n"));
491
err = -EINVAL;
492
return err;
493
}
494
num_channels = reply_len / sizeof(uint32);
495
mem_needed = reply_len + VENDOR_REPLY_OVERHEAD + (ATTRIBUTE_U32_LEN * 2);
496
497
/* Alloc the SKB for vendor_event */
498
skb = rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);
499
if (unlikely(!skb)) {
500
WL_ERR(("skb alloc failed"));
501
err = -ENOMEM;
502
goto exit;
503
}
504
505
nla_put_u32(skb, GSCAN_ATTRIBUTE_NUM_CHANNELS, num_channels);
506
nla_put(skb, GSCAN_ATTRIBUTE_CHANNEL_LIST, reply_len, reply);
507
508
err = rtw_cfg80211_vendor_cmd_reply(skb);
509
510
if (unlikely(err))
511
WL_ERR(("Vendor Command reply failed ret:%d\n", err));
512
exit:
513
kfree(reply);
514
return err;
515
}
516
517
static int rtw_cfgvendor_gscan_get_batch_results(struct wiphy *wiphy,
518
struct wireless_dev *wdev, const void *data, int len)
519
{
520
int err = 0;
521
struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
522
gscan_results_cache_t *results, *iter;
523
uint32 reply_len, complete = 0, num_results_iter;
524
int32 mem_needed;
525
wifi_gscan_result_t *ptr;
526
uint16 num_scan_ids, num_results;
527
struct sk_buff *skb;
528
struct nlattr *scan_hdr;
529
530
dhd_dev_wait_batch_results_complete(bcmcfg_to_prmry_ndev(cfg));
531
dhd_dev_pno_lock_access_batch_results(bcmcfg_to_prmry_ndev(cfg));
532
results = dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg),
533
DHD_PNO_GET_BATCH_RESULTS, NULL, &reply_len);
534
535
if (!results) {
536
WL_ERR(("No results to send %d\n", err));
537
err = rtw_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),
538
results, 0);
539
540
if (unlikely(err))
541
WL_ERR(("Vendor Command reply failed ret:%d\n", err));
542
dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg));
543
return err;
544
}
545
num_scan_ids = reply_len & 0xFFFF;
546
num_results = (reply_len & 0xFFFF0000) >> 16;
547
mem_needed = (num_results * sizeof(wifi_gscan_result_t)) +
548
(num_scan_ids * GSCAN_BATCH_RESULT_HDR_LEN) +
549
VENDOR_REPLY_OVERHEAD + SCAN_RESULTS_COMPLETE_FLAG_LEN;
550
551
if (mem_needed > (int32)NLMSG_DEFAULT_SIZE) {
552
mem_needed = (int32)NLMSG_DEFAULT_SIZE;
553
complete = 0;
554
} else
555
complete = 1;
556
557
WL_TRACE(("complete %d mem_needed %d max_mem %d\n", complete, mem_needed,
558
(int)NLMSG_DEFAULT_SIZE));
559
/* Alloc the SKB for vendor_event */
560
skb = rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);
561
if (unlikely(!skb)) {
562
WL_ERR(("skb alloc failed"));
563
dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg));
564
return -ENOMEM;
565
}
566
iter = results;
567
568
nla_put_u32(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, complete);
569
570
mem_needed = mem_needed - (SCAN_RESULTS_COMPLETE_FLAG_LEN + VENDOR_REPLY_OVERHEAD);
571
572
while (iter && ((mem_needed - GSCAN_BATCH_RESULT_HDR_LEN) > 0)) {
573
scan_hdr = nla_nest_start(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS);
574
nla_put_u32(skb, GSCAN_ATTRIBUTE_SCAN_ID, iter->scan_id);
575
nla_put_u8(skb, GSCAN_ATTRIBUTE_SCAN_FLAGS, iter->flag);
576
num_results_iter =
577
(mem_needed - GSCAN_BATCH_RESULT_HDR_LEN) / sizeof(wifi_gscan_result_t);
578
579
if ((iter->tot_count - iter->tot_consumed) < num_results_iter)
580
num_results_iter = iter->tot_count - iter->tot_consumed;
581
582
nla_put_u32(skb, GSCAN_ATTRIBUTE_NUM_OF_RESULTS, num_results_iter);
583
if (num_results_iter) {
584
ptr = &iter->results[iter->tot_consumed];
585
iter->tot_consumed += num_results_iter;
586
nla_put(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS,
587
num_results_iter * sizeof(wifi_gscan_result_t), ptr);
588
}
589
nla_nest_end(skb, scan_hdr);
590
mem_needed -= GSCAN_BATCH_RESULT_HDR_LEN +
591
(num_results_iter * sizeof(wifi_gscan_result_t));
592
iter = iter->next;
593
}
594
595
dhd_dev_gscan_batch_cache_cleanup(bcmcfg_to_prmry_ndev(cfg));
596
dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg));
597
598
return rtw_cfg80211_vendor_cmd_reply(skb);
599
}
600
601
static int rtw_cfgvendor_initiate_gscan(struct wiphy *wiphy,
602
struct wireless_dev *wdev, const void *data, int len)
603
{
604
int err = 0;
605
struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
606
int type, tmp = len;
607
int run = 0xFF;
608
int flush = 0;
609
const struct nlattr *iter;
610
611
nla_for_each_attr(iter, data, len, tmp) {
612
type = nla_type(iter);
613
if (type == GSCAN_ATTRIBUTE_ENABLE_FEATURE)
614
run = nla_get_u32(iter);
615
else if (type == GSCAN_ATTRIBUTE_FLUSH_FEATURE)
616
flush = nla_get_u32(iter);
617
}
618
619
if (run != 0xFF) {
620
err = dhd_dev_pno_run_gscan(bcmcfg_to_prmry_ndev(cfg), run, flush);
621
622
if (unlikely(err))
623
WL_ERR(("Could not run gscan:%d\n", err));
624
return err;
625
} else
626
return -1;
627
628
629
}
630
631
static int rtw_cfgvendor_enable_full_scan_result(struct wiphy *wiphy,
632
struct wireless_dev *wdev, const void *data, int len)
633
{
634
int err = 0;
635
struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
636
int type;
637
bool real_time = FALSE;
638
639
type = nla_type(data);
640
641
if (type == GSCAN_ATTRIBUTE_ENABLE_FULL_SCAN_RESULTS) {
642
real_time = nla_get_u32(data);
643
644
err = dhd_dev_pno_enable_full_scan_result(bcmcfg_to_prmry_ndev(cfg), real_time);
645
646
if (unlikely(err))
647
WL_ERR(("Could not run gscan:%d\n", err));
648
649
} else
650
err = -1;
651
652
return err;
653
}
654
655
static int rtw_cfgvendor_set_scan_cfg(struct wiphy *wiphy,
656
struct wireless_dev *wdev, const void *data, int len)
657
{
658
int err = 0;
659
struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
660
gscan_scan_params_t *scan_param;
661
int j = 0;
662
int type, tmp, tmp1, tmp2, k = 0;
663
const struct nlattr *iter, *iter1, *iter2;
664
struct dhd_pno_gscan_channel_bucket *ch_bucket;
665
666
scan_param = kzalloc(sizeof(gscan_scan_params_t), GFP_KERNEL);
667
if (!scan_param) {
668
WL_ERR(("Could not set GSCAN scan cfg, mem alloc failure\n"));
669
err = -EINVAL;
670
return err;
671
672
}
673
674
scan_param->scan_fr = PNO_SCAN_MIN_FW_SEC;
675
nla_for_each_attr(iter, data, len, tmp) {
676
type = nla_type(iter);
677
678
if (j >= GSCAN_MAX_CH_BUCKETS)
679
break;
680
681
switch (type) {
682
case GSCAN_ATTRIBUTE_BASE_PERIOD:
683
scan_param->scan_fr = nla_get_u32(iter) / 1000;
684
break;
685
case GSCAN_ATTRIBUTE_NUM_BUCKETS:
686
scan_param->nchannel_buckets = nla_get_u32(iter);
687
break;
688
case GSCAN_ATTRIBUTE_CH_BUCKET_1:
689
case GSCAN_ATTRIBUTE_CH_BUCKET_2:
690
case GSCAN_ATTRIBUTE_CH_BUCKET_3:
691
case GSCAN_ATTRIBUTE_CH_BUCKET_4:
692
case GSCAN_ATTRIBUTE_CH_BUCKET_5:
693
case GSCAN_ATTRIBUTE_CH_BUCKET_6:
694
case GSCAN_ATTRIBUTE_CH_BUCKET_7:
695
nla_for_each_nested(iter1, iter, tmp1) {
696
type = nla_type(iter1);
697
ch_bucket =
698
scan_param->channel_bucket;
699
700
switch (type) {
701
case GSCAN_ATTRIBUTE_BUCKET_ID:
702
break;
703
case GSCAN_ATTRIBUTE_BUCKET_PERIOD:
704
ch_bucket[j].bucket_freq_multiple =
705
nla_get_u32(iter1) / 1000;
706
break;
707
case GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS:
708
ch_bucket[j].num_channels =
709
nla_get_u32(iter1);
710
break;
711
case GSCAN_ATTRIBUTE_BUCKET_CHANNELS:
712
nla_for_each_nested(iter2, iter1, tmp2) {
713
if (k >= PFN_SWC_RSSI_WINDOW_MAX)
714
break;
715
ch_bucket[j].chan_list[k] =
716
nla_get_u32(iter2);
717
k++;
718
}
719
k = 0;
720
break;
721
case GSCAN_ATTRIBUTE_BUCKETS_BAND:
722
ch_bucket[j].band = (uint16)
723
nla_get_u32(iter1);
724
break;
725
case GSCAN_ATTRIBUTE_REPORT_EVENTS:
726
ch_bucket[j].report_flag = (uint8)
727
nla_get_u32(iter1);
728
break;
729
}
730
}
731
j++;
732
break;
733
}
734
}
735
736
if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
737
DHD_PNO_SCAN_CFG_ID, scan_param, 0) < 0) {
738
WL_ERR(("Could not set GSCAN scan cfg\n"));
739
err = -EINVAL;
740
}
741
742
kfree(scan_param);
743
return err;
744
745
}
746
747
static int rtw_cfgvendor_hotlist_cfg(struct wiphy *wiphy,
748
struct wireless_dev *wdev, const void *data, int len)
749
{
750
int err = 0;
751
struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
752
gscan_hotlist_scan_params_t *hotlist_params;
753
int tmp, tmp1, tmp2, type, j = 0, dummy;
754
const struct nlattr *outer, *inner, *iter;
755
uint8 flush = 0;
756
struct bssid_t *pbssid;
757
758
hotlist_params = (gscan_hotlist_scan_params_t *)kzalloc(len, GFP_KERNEL);
759
if (!hotlist_params) {
760
WL_ERR(("Cannot Malloc mem to parse config commands size - %d bytes\n", len));
761
return -1;
762
}
763
764
hotlist_params->lost_ap_window = GSCAN_LOST_AP_WINDOW_DEFAULT;
765
766
nla_for_each_attr(iter, data, len, tmp2) {
767
type = nla_type(iter);
768
switch (type) {
769
case GSCAN_ATTRIBUTE_HOTLIST_BSSIDS:
770
pbssid = hotlist_params->bssid;
771
nla_for_each_nested(outer, iter, tmp) {
772
nla_for_each_nested(inner, outer, tmp1) {
773
type = nla_type(inner);
774
775
switch (type) {
776
case GSCAN_ATTRIBUTE_BSSID:
777
memcpy(&(pbssid[j].macaddr),
778
nla_data(inner), ETHER_ADDR_LEN);
779
break;
780
case GSCAN_ATTRIBUTE_RSSI_LOW:
781
pbssid[j].rssi_reporting_threshold =
782
(int8) nla_get_u8(inner);
783
break;
784
case GSCAN_ATTRIBUTE_RSSI_HIGH:
785
dummy = (int8) nla_get_u8(inner);
786
break;
787
}
788
}
789
j++;
790
}
791
hotlist_params->nbssid = j;
792
break;
793
case GSCAN_ATTRIBUTE_HOTLIST_FLUSH:
794
flush = nla_get_u8(iter);
795
break;
796
case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE:
797
hotlist_params->lost_ap_window = nla_get_u32(iter);
798
break;
799
}
800
801
}
802
803
if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
804
DHD_PNO_GEOFENCE_SCAN_CFG_ID, hotlist_params, flush) < 0) {
805
WL_ERR(("Could not set GSCAN HOTLIST cfg\n"));
806
err = -EINVAL;
807
goto exit;
808
}
809
exit:
810
kfree(hotlist_params);
811
return err;
812
}
813
static int rtw_cfgvendor_set_batch_scan_cfg(struct wiphy *wiphy,
814
struct wireless_dev *wdev, const void *data, int len)
815
{
816
int err = 0, tmp, type;
817
struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
818
gscan_batch_params_t batch_param;
819
const struct nlattr *iter;
820
821
batch_param.mscan = batch_param.bestn = 0;
822
batch_param.buffer_threshold = GSCAN_BATCH_NO_THR_SET;
823
824
nla_for_each_attr(iter, data, len, tmp) {
825
type = nla_type(iter);
826
827
switch (type) {
828
case GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN:
829
batch_param.bestn = nla_get_u32(iter);
830
break;
831
case GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE:
832
batch_param.mscan = nla_get_u32(iter);
833
break;
834
case GSCAN_ATTRIBUTE_REPORT_THRESHOLD:
835
batch_param.buffer_threshold = nla_get_u32(iter);
836
break;
837
}
838
}
839
840
if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
841
DHD_PNO_BATCH_SCAN_CFG_ID, &batch_param, 0) < 0) {
842
WL_ERR(("Could not set batch cfg\n"));
843
err = -EINVAL;
844
return err;
845
}
846
847
return err;
848
}
849
850
static int rtw_cfgvendor_significant_change_cfg(struct wiphy *wiphy,
851
struct wireless_dev *wdev, const void *data, int len)
852
{
853
int err = 0;
854
struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
855
gscan_swc_params_t *significant_params;
856
int tmp, tmp1, tmp2, type, j = 0;
857
const struct nlattr *outer, *inner, *iter;
858
uint8 flush = 0;
859
wl_pfn_significant_bssid_t *pbssid;
860
861
significant_params = (gscan_swc_params_t *) kzalloc(len, GFP_KERNEL);
862
if (!significant_params) {
863
WL_ERR(("Cannot Malloc mem to parse config commands size - %d bytes\n", len));
864
return -1;
865
}
866
867
868
nla_for_each_attr(iter, data, len, tmp2) {
869
type = nla_type(iter);
870
871
switch (type) {
872
case GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH:
873
flush = nla_get_u8(iter);
874
break;
875
case GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE:
876
significant_params->rssi_window = nla_get_u16(iter);
877
break;
878
case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE:
879
significant_params->lost_ap_window = nla_get_u16(iter);
880
break;
881
case GSCAN_ATTRIBUTE_MIN_BREACHING:
882
significant_params->swc_threshold = nla_get_u16(iter);
883
break;
884
case GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS:
885
pbssid = significant_params->bssid_elem_list;
886
nla_for_each_nested(outer, iter, tmp) {
887
nla_for_each_nested(inner, outer, tmp1) {
888
switch (nla_type(inner)) {
889
case GSCAN_ATTRIBUTE_BSSID:
890
memcpy(&(pbssid[j].macaddr),
891
nla_data(inner),
892
ETHER_ADDR_LEN);
893
break;
894
case GSCAN_ATTRIBUTE_RSSI_HIGH:
895
pbssid[j].rssi_high_threshold =
896
(int8) nla_get_u8(inner);
897
break;
898
case GSCAN_ATTRIBUTE_RSSI_LOW:
899
pbssid[j].rssi_low_threshold =
900
(int8) nla_get_u8(inner);
901
break;
902
}
903
}
904
j++;
905
}
906
break;
907
}
908
}
909
significant_params->nbssid = j;
910
911
if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
912
DHD_PNO_SIGNIFICANT_SCAN_CFG_ID, significant_params, flush) < 0) {
913
WL_ERR(("Could not set GSCAN significant cfg\n"));
914
err = -EINVAL;
915
goto exit;
916
}
917
exit:
918
kfree(significant_params);
919
return err;
920
}
921
#endif /* GSCAN_SUPPORT */
922
923
#if defined(RTT_SUPPORT) && 0
924
void rtw_cfgvendor_rtt_evt(void *ctx, void *rtt_data)
925
{
926
struct wireless_dev *wdev = (struct wireless_dev *)ctx;
927
struct wiphy *wiphy;
928
struct sk_buff *skb;
929
uint32 tot_len = NLMSG_DEFAULT_SIZE, entry_len = 0;
930
gfp_t kflags;
931
rtt_report_t *rtt_report = NULL;
932
rtt_result_t *rtt_result = NULL;
933
struct list_head *rtt_list;
934
wiphy = wdev->wiphy;
935
936
WL_DBG(("In\n"));
937
/* Push the data to the skb */
938
if (!rtt_data) {
939
WL_ERR(("rtt_data is NULL\n"));
940
goto exit;
941
}
942
rtt_list = (struct list_head *)rtt_data;
943
kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
944
/* Alloc the SKB for vendor_event */
945
skb = rtw_cfg80211_vendor_event_alloc(wiphy, wdev, tot_len, GOOGLE_RTT_COMPLETE_EVENT, kflags);
946
if (!skb) {
947
WL_ERR(("skb alloc failed"));
948
goto exit;
949
}
950
/* fill in the rtt results on each entry */
951
list_for_each_entry(rtt_result, rtt_list, list) {
952
entry_len = 0;
953
if (rtt_result->TOF_type == TOF_TYPE_ONE_WAY) {
954
entry_len = sizeof(rtt_report_t);
955
rtt_report = kzalloc(entry_len, kflags);
956
if (!rtt_report) {
957
WL_ERR(("rtt_report alloc failed"));
958
goto exit;
959
}
960
rtt_report->addr = rtt_result->peer_mac;
961
rtt_report->num_measurement = 1; /* ONE SHOT */
962
rtt_report->status = rtt_result->err_code;
963
rtt_report->type = (rtt_result->TOF_type == TOF_TYPE_ONE_WAY) ? RTT_ONE_WAY : RTT_TWO_WAY;
964
rtt_report->peer = rtt_result->target_info->peer;
965
rtt_report->channel = rtt_result->target_info->channel;
966
rtt_report->rssi = rtt_result->avg_rssi;
967
/* tx_rate */
968
rtt_report->tx_rate = rtt_result->tx_rate;
969
/* RTT */
970
rtt_report->rtt = rtt_result->meanrtt;
971
rtt_report->rtt_sd = rtt_result->sdrtt;
972
/* convert to centi meter */
973
if (rtt_result->distance != 0xffffffff)
974
rtt_report->distance = (rtt_result->distance >> 2) * 25;
975
else /* invalid distance */
976
rtt_report->distance = -1;
977
978
rtt_report->ts = rtt_result->ts;
979
nla_append(skb, entry_len, rtt_report);
980
kfree(rtt_report);
981
}
982
}
983
rtw_cfg80211_vendor_event(skb, kflags);
984
exit:
985
return;
986
}
987
988
static int rtw_cfgvendor_rtt_set_config(struct wiphy *wiphy, struct wireless_dev *wdev,
989
const void *data, int len)
990
{
991
int err = 0, rem, rem1, rem2, type;
992
rtt_config_params_t rtt_param;
993
rtt_target_info_t *rtt_target = NULL;
994
const struct nlattr *iter, *iter1, *iter2;
995
int8 eabuf[ETHER_ADDR_STR_LEN];
996
int8 chanbuf[CHANSPEC_STR_LEN];
997
struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
998
999
WL_DBG(("In\n"));
1000
err = dhd_dev_rtt_register_noti_callback(wdev->netdev, wdev, wl_cfgvendor_rtt_evt);
1001
if (err < 0) {
1002
WL_ERR(("failed to register rtt_noti_callback\n"));
1003
goto exit;
1004
}
1005
memset(&rtt_param, 0, sizeof(rtt_param));
1006
nla_for_each_attr(iter, data, len, rem) {
1007
type = nla_type(iter);
1008
switch (type) {
1009
case RTT_ATTRIBUTE_TARGET_CNT:
1010
rtt_param.rtt_target_cnt = nla_get_u8(iter);
1011
if (rtt_param.rtt_target_cnt > RTT_MAX_TARGET_CNT) {
1012
WL_ERR(("exceed max target count : %d\n",
1013
rtt_param.rtt_target_cnt));
1014
err = BCME_RANGE;
1015
}
1016
break;
1017
case RTT_ATTRIBUTE_TARGET_INFO:
1018
rtt_target = rtt_param.target_info;
1019
nla_for_each_nested(iter1, iter, rem1) {
1020
nla_for_each_nested(iter2, iter1, rem2) {
1021
type = nla_type(iter2);
1022
switch (type) {
1023
case RTT_ATTRIBUTE_TARGET_MAC:
1024
memcpy(&rtt_target->addr, nla_data(iter2), ETHER_ADDR_LEN);
1025
break;
1026
case RTT_ATTRIBUTE_TARGET_TYPE:
1027
rtt_target->type = nla_get_u8(iter2);
1028
break;
1029
case RTT_ATTRIBUTE_TARGET_PEER:
1030
rtt_target->peer = nla_get_u8(iter2);
1031
break;
1032
case RTT_ATTRIBUTE_TARGET_CHAN:
1033
memcpy(&rtt_target->channel, nla_data(iter2),
1034
sizeof(rtt_target->channel));
1035
break;
1036
case RTT_ATTRIBUTE_TARGET_MODE:
1037
rtt_target->continuous = nla_get_u8(iter2);
1038
break;
1039
case RTT_ATTRIBUTE_TARGET_INTERVAL:
1040
rtt_target->interval = nla_get_u32(iter2);
1041
break;
1042
case RTT_ATTRIBUTE_TARGET_NUM_MEASUREMENT:
1043
rtt_target->measure_cnt = nla_get_u32(iter2);
1044
break;
1045
case RTT_ATTRIBUTE_TARGET_NUM_PKT:
1046
rtt_target->ftm_cnt = nla_get_u32(iter2);
1047
break;
1048
case RTT_ATTRIBUTE_TARGET_NUM_RETRY:
1049
rtt_target->retry_cnt = nla_get_u32(iter2);
1050
}
1051
}
1052
/* convert to chanspec value */
1053
rtt_target->chanspec = dhd_rtt_convert_to_chspec(rtt_target->channel);
1054
if (rtt_target->chanspec == 0) {
1055
WL_ERR(("Channel is not valid\n"));
1056
goto exit;
1057
}
1058
WL_INFORM(("Target addr %s, Channel : %s for RTT\n",
1059
bcm_ether_ntoa((const struct ether_addr *)&rtt_target->addr, eabuf),
1060
wf_chspec_ntoa(rtt_target->chanspec, chanbuf)));
1061
rtt_target++;
1062
}
1063
break;
1064
}
1065
}
1066
WL_DBG(("leave :target_cnt : %d\n", rtt_param.rtt_target_cnt));
1067
if (dhd_dev_rtt_set_cfg(bcmcfg_to_prmry_ndev(cfg), &rtt_param) < 0) {
1068
WL_ERR(("Could not set RTT configuration\n"));
1069
err = -EINVAL;
1070
}
1071
exit:
1072
return err;
1073
}
1074
1075
static int rtw_cfgvendor_rtt_cancel_config(struct wiphy *wiphy, struct wireless_dev *wdev,
1076
const void *data, int len)
1077
{
1078
int err = 0, rem, type, target_cnt = 0;
1079
const struct nlattr *iter;
1080
struct ether_addr *mac_list = NULL, *mac_addr = NULL;
1081
struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1082
1083
nla_for_each_attr(iter, data, len, rem) {
1084
type = nla_type(iter);
1085
switch (type) {
1086
case RTT_ATTRIBUTE_TARGET_CNT:
1087
target_cnt = nla_get_u8(iter);
1088
mac_list = (struct ether_addr *)kzalloc(target_cnt * ETHER_ADDR_LEN , GFP_KERNEL);
1089
if (mac_list == NULL) {
1090
WL_ERR(("failed to allocate mem for mac list\n"));
1091
goto exit;
1092
}
1093
mac_addr = &mac_list[0];
1094
break;
1095
case RTT_ATTRIBUTE_TARGET_MAC:
1096
if (mac_addr)
1097
memcpy(mac_addr++, nla_data(iter), ETHER_ADDR_LEN);
1098
else {
1099
WL_ERR(("mac_list is NULL\n"));
1100
goto exit;
1101
}
1102
break;
1103
}
1104
if (dhd_dev_rtt_cancel_cfg(bcmcfg_to_prmry_ndev(cfg), mac_list, target_cnt) < 0) {
1105
WL_ERR(("Could not cancel RTT configuration\n"));
1106
err = -EINVAL;
1107
goto exit;
1108
}
1109
}
1110
exit:
1111
if (mac_list)
1112
kfree(mac_list);
1113
return err;
1114
}
1115
static int rtw_cfgvendor_rtt_get_capability(struct wiphy *wiphy, struct wireless_dev *wdev,
1116
const void *data, int len)
1117
{
1118
int err = 0;
1119
struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1120
rtt_capabilities_t capability;
1121
1122
err = dhd_dev_rtt_capability(bcmcfg_to_prmry_ndev(cfg), &capability);
1123
if (unlikely(err)) {
1124
WL_ERR(("Vendor Command reply failed ret:%d\n", err));
1125
goto exit;
1126
}
1127
err = rtw_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),
1128
&capability, sizeof(capability));
1129
1130
if (unlikely(err))
1131
WL_ERR(("Vendor Command reply failed ret:%d\n", err));
1132
exit:
1133
return err;
1134
}
1135
1136
#endif /* RTT_SUPPORT */
1137
1138
#ifdef CONFIG_RTW_CFGVEDNOR_LLSTATS
1139
enum {
1140
LSTATS_SUBCMD_GET_INFO = ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START,
1141
LSTATS_SUBCMD_SET_INFO,
1142
LSTATS_SUBCMD_CLEAR_INFO,
1143
};
1144
static void LinkLayerStats(_adapter *padapter)
1145
{
1146
struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
1147
struct recv_priv *precvpriv = &(padapter->recvpriv);
1148
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
1149
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
1150
u32 ps_time, trx_total_time;
1151
u64 tx_bytes, rx_bytes, trx_total_bytes = 0;
1152
u64 tmp = 0;
1153
1154
RTW_DBG("%s adapter type : %u\n", __func__, padapter->adapter_type);
1155
1156
tx_bytes = 0;
1157
rx_bytes = 0;
1158
ps_time = 0;
1159
trx_total_time = 0;
1160
1161
if ( padapter->netif_up == _TRUE ) {
1162
1163
pwrpriv->on_time = rtw_get_passing_time_ms(pwrpriv->radio_on_start_time);
1164
1165
if (rtw_mi_check_fwstate(padapter, _FW_LINKED)) {
1166
if ( pwrpriv->bpower_saving == _TRUE ) {
1167
pwrpriv->pwr_saving_time += rtw_get_passing_time_ms(pwrpriv->pwr_saving_start_time);
1168
pwrpriv->pwr_saving_start_time = rtw_get_current_time();
1169
}
1170
} else {
1171
#ifdef CONFIG_IPS
1172
if ( pwrpriv->bpower_saving == _TRUE ) {
1173
pwrpriv->pwr_saving_time += rtw_get_passing_time_ms(pwrpriv->pwr_saving_start_time);
1174
pwrpriv->pwr_saving_start_time = rtw_get_current_time();
1175
}
1176
#else
1177
pwrpriv->pwr_saving_time = pwrpriv->on_time;
1178
#endif
1179
}
1180
1181
ps_time = pwrpriv->pwr_saving_time;
1182
1183
/* Deviation caused by caculation start time */
1184
if ( ps_time > pwrpriv->on_time )
1185
ps_time = pwrpriv->on_time;
1186
1187
tx_bytes = pdvobjpriv->traffic_stat.last_tx_bytes;
1188
rx_bytes = pdvobjpriv->traffic_stat.last_rx_bytes;
1189
trx_total_bytes = tx_bytes + rx_bytes;
1190
1191
trx_total_time = pwrpriv->on_time - ps_time;
1192
1193
if ( trx_total_bytes == 0) {
1194
pwrpriv->tx_time = 0;
1195
pwrpriv->rx_time = 0;
1196
} else {
1197
1198
/* tx_time = (trx_total_time * tx_total_bytes) / trx_total_bytes; */
1199
/* rx_time = (trx_total_time * rx_total_bytes) / trx_total_bytes; */
1200
1201
tmp = (tx_bytes * trx_total_time);
1202
tmp = rtw_division64(tmp, trx_total_bytes);
1203
pwrpriv->tx_time = tmp;
1204
1205
tmp = (rx_bytes * trx_total_time);
1206
tmp = rtw_division64(tmp, trx_total_bytes);
1207
pwrpriv->rx_time = tmp;
1208
1209
}
1210
1211
}
1212
else {
1213
pwrpriv->on_time = 0;
1214
pwrpriv->tx_time = 0;
1215
pwrpriv->rx_time = 0;
1216
}
1217
1218
#ifdef CONFIG_RTW_WIFI_HAL_DEBUG
1219
RTW_INFO("- tx_bytes : %llu rx_bytes : %llu total bytes : %llu\n", tx_bytes, rx_bytes, trx_total_bytes);
1220
RTW_INFO("- netif_up = %s, on_time : %u ms\n", padapter->netif_up ? "1":"0", pwrpriv->on_time);
1221
RTW_INFO("- pwr_saving_time : %u (%u) ms\n", pwrpriv->pwr_saving_time, ps_time);
1222
RTW_INFO("- trx_total_time : %u ms\n", trx_total_time);
1223
RTW_INFO("- tx_time : %u ms\n", pwrpriv->tx_time);
1224
RTW_INFO("- rx_time : %u ms\n", pwrpriv->rx_time);
1225
#endif /* CONFIG_RTW_WIFI_HAL_DEBUG */
1226
1227
}
1228
1229
#define DUMMY_TIME_STATICS 99
1230
static int rtw_cfgvendor_lstats_get_info(struct wiphy *wiphy,
1231
struct wireless_dev *wdev, const void *data, int len)
1232
{
1233
int err = 0;
1234
_adapter *padapter = GET_PRIMARY_ADAPTER(wiphy_to_adapter(wiphy));
1235
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
1236
wifi_radio_stat_internal *radio;
1237
wifi_iface_stat *iface;
1238
char *output;
1239
1240
output = rtw_malloc(sizeof(wifi_radio_stat_internal) + sizeof(wifi_iface_stat));
1241
if (output == NULL) {
1242
RTW_DBG("Allocate lstats info buffer fail!\n");
1243
}
1244
1245
radio = (wifi_radio_stat_internal *)output;
1246
1247
radio->num_channels = 0;
1248
radio->radio = 1;
1249
1250
/* to get on_time, tx_time, rx_time */
1251
LinkLayerStats(padapter);
1252
1253
radio->on_time = pwrpriv->on_time;
1254
radio->tx_time = pwrpriv->tx_time;
1255
radio->rx_time = pwrpriv->rx_time;
1256
radio->on_time_scan = 0;
1257
radio->on_time_nbd = 0;
1258
radio->on_time_gscan = 0;
1259
radio->on_time_pno_scan = 0;
1260
radio->on_time_hs20 = 0;
1261
#ifdef CONFIG_RTW_WIFI_HAL_DEBUG
1262
RTW_INFO("==== %s ====\n", __func__);
1263
RTW_INFO("radio->radio : %d\n", (radio->radio));
1264
RTW_INFO("pwrpriv->on_time : %u ms\n", (pwrpriv->on_time));
1265
RTW_INFO("pwrpriv->tx_time : %u ms\n", (pwrpriv->tx_time));
1266
RTW_INFO("pwrpriv->rx_time : %u ms\n", (pwrpriv->rx_time));
1267
RTW_INFO("radio->on_time : %u ms\n", (radio->on_time));
1268
RTW_INFO("radio->tx_time : %u ms\n", (radio->tx_time));
1269
RTW_INFO("radio->rx_time : %u ms\n", (radio->rx_time));
1270
#endif /* CONFIG_RTW_WIFI_HAL_DEBUG */
1271
1272
RTW_DBG(FUNC_NDEV_FMT" %s\n", FUNC_NDEV_ARG(wdev_to_ndev(wdev)), (char*)data);
1273
err = rtw_cfgvendor_send_cmd_reply(wiphy, wdev_to_ndev(wdev),
1274
output, sizeof(wifi_iface_stat) + sizeof(wifi_radio_stat_internal));
1275
if (unlikely(err))
1276
RTW_ERR(FUNC_NDEV_FMT"Vendor Command reply failed ret:%d \n"
1277
, FUNC_NDEV_ARG(wdev_to_ndev(wdev)), err);
1278
rtw_mfree(output, sizeof(wifi_iface_stat) + sizeof(wifi_radio_stat_internal));
1279
return err;
1280
}
1281
static int rtw_cfgvendor_lstats_set_info(struct wiphy *wiphy,
1282
struct wireless_dev *wdev, const void *data, int len)
1283
{
1284
int err = 0;
1285
RTW_INFO("%s\n", __func__);
1286
return err;
1287
}
1288
static int rtw_cfgvendor_lstats_clear_info(struct wiphy *wiphy,
1289
struct wireless_dev *wdev, const void *data, int len)
1290
{
1291
int err = 0;
1292
RTW_INFO("%s\n", __func__);
1293
return err;
1294
}
1295
#endif /* CONFIG_RTW_CFGVEDNOR_LLSTATS */
1296
#ifdef CONFIG_RTW_CFGVEDNOR_RSSIMONITOR
1297
static int rtw_cfgvendor_set_rssi_monitor(struct wiphy *wiphy,
1298
struct wireless_dev *wdev, const void *data, int len)
1299
{
1300
_adapter *padapter = GET_PRIMARY_ADAPTER(wiphy_to_adapter(wiphy));
1301
struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
1302
1303
struct recv_priv *precvpriv = &padapter->recvpriv;
1304
int err = 0, rem, type;
1305
const struct nlattr *iter;
1306
1307
RTW_DBG(FUNC_NDEV_FMT" %s\n", FUNC_NDEV_ARG(wdev_to_ndev(wdev)), (char*)data);
1308
1309
nla_for_each_attr(iter, data, len, rem) {
1310
type = nla_type(iter);
1311
1312
switch (type) {
1313
case RSSI_MONITOR_ATTRIBUTE_MAX_RSSI:
1314
pwdev_priv->rssi_monitor_max = (s8)nla_get_u32(iter);;
1315
break;
1316
case RSSI_MONITOR_ATTRIBUTE_MIN_RSSI:
1317
pwdev_priv->rssi_monitor_min = (s8)nla_get_u32(iter);
1318
break;
1319
case RSSI_MONITOR_ATTRIBUTE_START:
1320
pwdev_priv->rssi_monitor_enable = (u8)nla_get_u32(iter);
1321
break;
1322
}
1323
}
1324
1325
return err;
1326
}
1327
1328
void rtw_cfgvendor_rssi_monitor_evt(_adapter *padapter) {
1329
struct wireless_dev *wdev = padapter->rtw_wdev;
1330
struct wiphy *wiphy= wdev->wiphy;
1331
struct recv_priv *precvpriv = &padapter->recvpriv;
1332
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1333
struct wlan_network *pcur_network = &pmlmepriv->cur_network;
1334
struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
1335
struct sk_buff *skb;
1336
u32 tot_len = NLMSG_DEFAULT_SIZE;
1337
gfp_t kflags;
1338
rssi_monitor_evt data ;
1339
s8 rssi = precvpriv->rssi;
1340
1341
if (pwdev_priv->rssi_monitor_enable == 0 || check_fwstate(pmlmepriv, _FW_LINKED) != _TRUE)
1342
return;
1343
1344
if (rssi < pwdev_priv->rssi_monitor_max || rssi > pwdev_priv->rssi_monitor_min)
1345
return;
1346
1347
kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
1348
1349
/* Alloc the SKB for vendor_event */
1350
skb = rtw_cfg80211_vendor_event_alloc(wiphy, wdev, tot_len, GOOGLE_RSSI_MONITOR_EVENT, kflags);
1351
if (!skb) {
1352
goto exit;
1353
}
1354
1355
_rtw_memset(&data, 0, sizeof(data));
1356
1357
data.version = RSSI_MONITOR_EVT_VERSION;
1358
data.cur_rssi = rssi;
1359
_rtw_memcpy(data.BSSID, pcur_network->network.MacAddress, sizeof(mac_addr));
1360
1361
nla_append(skb, sizeof(data), &data);
1362
1363
rtw_cfg80211_vendor_event(skb, kflags);
1364
exit:
1365
return;
1366
}
1367
#endif /* CONFIG_RTW_CFGVEDNOR_RSSIMONITR */
1368
1369
#ifdef CONFIG_RTW_CFGVENDOR_WIFI_LOGGER
1370
static int rtw_cfgvendor_logger_start_logging(struct wiphy *wiphy,
1371
struct wireless_dev *wdev, const void *data, int len)
1372
{
1373
int ret = 0, rem, type;
1374
char ring_name[32] = {0};
1375
int log_level = 0, flags = 0, time_intval = 0, threshold = 0;
1376
const struct nlattr *iter;
1377
1378
nla_for_each_attr(iter, data, len, rem) {
1379
type = nla_type(iter);
1380
switch (type) {
1381
case LOGGER_ATTRIBUTE_RING_NAME:
1382
strncpy(ring_name, nla_data(iter),
1383
MIN(sizeof(ring_name) -1, nla_len(iter)));
1384
break;
1385
case LOGGER_ATTRIBUTE_LOG_LEVEL:
1386
log_level = nla_get_u32(iter);
1387
break;
1388
case LOGGER_ATTRIBUTE_RING_FLAGS:
1389
flags = nla_get_u32(iter);
1390
break;
1391
case LOGGER_ATTRIBUTE_LOG_TIME_INTVAL:
1392
time_intval = nla_get_u32(iter);
1393
break;
1394
case LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE:
1395
threshold = nla_get_u32(iter);
1396
break;
1397
default:
1398
RTW_ERR("Unknown type: %d\n", type);
1399
ret = WIFI_ERROR_INVALID_ARGS;
1400
goto exit;
1401
}
1402
}
1403
1404
exit:
1405
return ret;
1406
}
1407
static int rtw_cfgvendor_logger_get_feature(struct wiphy *wiphy,
1408
struct wireless_dev *wdev, const void *data, int len)
1409
{
1410
int err = 0;
1411
u32 supported_features = 0;
1412
1413
err = rtw_cfgvendor_send_cmd_reply(wiphy, wdev_to_ndev(wdev), &supported_features, sizeof(supported_features));
1414
1415
if (unlikely(err))
1416
RTW_ERR(FUNC_NDEV_FMT" Vendor Command reply failed ret:%d\n"
1417
, FUNC_NDEV_ARG(wdev_to_ndev(wdev)), err);
1418
1419
return err;
1420
}
1421
static int rtw_cfgvendor_logger_get_version(struct wiphy *wiphy,
1422
struct wireless_dev *wdev, const void *data, int len)
1423
{
1424
_adapter *padapter = GET_PRIMARY_ADAPTER(wiphy_to_adapter(wiphy));
1425
HAL_DATA_TYPE *hal = GET_HAL_DATA(padapter);
1426
int ret = 0, rem, type;
1427
int buf_len = 1024;
1428
char *buf_ptr;
1429
const struct nlattr *iter;
1430
gfp_t kflags;
1431
1432
kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
1433
buf_ptr = kzalloc(buf_len, kflags);
1434
if (!buf_ptr) {
1435
RTW_ERR("failed to allocate the buffer for version n");
1436
ret = -ENOMEM;
1437
goto exit;
1438
}
1439
nla_for_each_attr(iter, data, len, rem) {
1440
type = nla_type(iter);
1441
switch (type) {
1442
case LOGGER_ATTRIBUTE_GET_DRIVER:
1443
memcpy(buf_ptr, DRIVERVERSION, strlen(DRIVERVERSION)+1);
1444
break;
1445
case LOGGER_ATTRIBUTE_GET_FW:
1446
sprintf(buf_ptr, "v%d.%d", hal->firmware_version, hal->firmware_sub_version);
1447
break;
1448
default:
1449
RTW_ERR("Unknown type: %d\n", type);
1450
ret = -EINVAL;
1451
goto exit;
1452
}
1453
}
1454
if (ret < 0) {
1455
RTW_ERR("failed to get the version %d\n", ret);
1456
goto exit;
1457
}
1458
1459
1460
ret = rtw_cfgvendor_send_cmd_reply(wiphy, wdev_to_ndev(wdev), buf_ptr, strlen(buf_ptr));
1461
exit:
1462
kfree(buf_ptr);
1463
return ret;
1464
}
1465
1466
static int rtw_cfgvendor_logger_get_ring_status(struct wiphy *wiphy,
1467
struct wireless_dev *wdev, const void *data, int len)
1468
{
1469
int ret = 0;
1470
int ring_id;
1471
char ring_buf_name[] = "RTW_RING_BUFFER";
1472
1473
struct sk_buff *skb;
1474
wifi_ring_buffer_status ring_status;
1475
1476
1477
_rtw_memcpy(ring_status.name, ring_buf_name, strlen(ring_buf_name)+1);
1478
ring_status.ring_id = 1;
1479
/* Alloc the SKB for vendor_event */
1480
skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1481
sizeof(wifi_ring_buffer_status));
1482
if (!skb) {
1483
RTW_ERR("skb allocation is failed\n");
1484
ret = FAIL;
1485
goto exit;
1486
}
1487
1488
nla_put_u32(skb, LOGGER_ATTRIBUTE_RING_NUM, 1);
1489
nla_put(skb, LOGGER_ATTRIBUTE_RING_STATUS, sizeof(wifi_ring_buffer_status),
1490
&ring_status);
1491
ret = cfg80211_vendor_cmd_reply(skb);
1492
1493
if (ret) {
1494
RTW_ERR("Vendor Command reply failed ret:%d \n", ret);
1495
}
1496
exit:
1497
return ret;
1498
}
1499
1500
static int rtw_cfgvendor_logger_get_ring_data(struct wiphy *wiphy,
1501
struct wireless_dev *wdev, const void *data, int len)
1502
{
1503
int ret = 0, rem, type;
1504
char ring_name[32] = {0};
1505
const struct nlattr *iter;
1506
1507
nla_for_each_attr(iter, data, len, rem) {
1508
type = nla_type(iter);
1509
switch (type) {
1510
case LOGGER_ATTRIBUTE_RING_NAME:
1511
strncpy(ring_name, nla_data(iter),
1512
MIN(sizeof(ring_name) -1, nla_len(iter)));
1513
RTW_INFO(" %s LOGGER_ATTRIBUTE_RING_NAME : %s\n", __func__, ring_name);
1514
break;
1515
default:
1516
RTW_ERR("Unknown type: %d\n", type);
1517
return ret;
1518
}
1519
}
1520
1521
1522
return ret;
1523
}
1524
1525
static int rtw_cfgvendor_logger_get_firmware_memory_dump(struct wiphy *wiphy,
1526
struct wireless_dev *wdev, const void *data, int len)
1527
{
1528
int ret = WIFI_ERROR_NOT_SUPPORTED;
1529
1530
return ret;
1531
}
1532
1533
static int rtw_cfgvendor_logger_start_pkt_fate_monitoring(struct wiphy *wiphy,
1534
struct wireless_dev *wdev, const void *data, int len)
1535
{
1536
int ret = WIFI_SUCCESS;
1537
1538
return ret;
1539
}
1540
1541
static int rtw_cfgvendor_logger_get_tx_pkt_fates(struct wiphy *wiphy,
1542
struct wireless_dev *wdev, const void *data, int len)
1543
{
1544
int ret = WIFI_SUCCESS;
1545
1546
return ret;
1547
}
1548
1549
static int rtw_cfgvendor_logger_get_rx_pkt_fates(struct wiphy *wiphy,
1550
struct wireless_dev *wdev, const void *data, int len)
1551
{
1552
int ret = WIFI_SUCCESS;
1553
1554
return ret;
1555
}
1556
1557
#endif /* CONFIG_RTW_CFGVENDOR_WIFI_LOGGER */
1558
#ifdef CONFIG_RTW_WIFI_HAL
1559
#ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI
1560
1561
#ifndef ETHER_ISMULTI
1562
#define ETHER_ISMULTI(ea) (((const u8 *)(ea))[0] & 1)
1563
#endif
1564
1565
1566
static u8 null_addr[ETH_ALEN] = {0};
1567
static void rtw_hal_random_gen_mac_addr(u8 *mac_addr)
1568
{
1569
do {
1570
get_random_bytes(&mac_addr[3], ETH_ALEN-3);
1571
if (memcmp(mac_addr, null_addr, ETH_ALEN) != 0)
1572
break;
1573
} while(1);
1574
}
1575
1576
void rtw_hal_pno_random_gen_mac_addr(PADAPTER adapter)
1577
{
1578
u8 mac_addr[ETH_ALEN];
1579
struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);
1580
1581
memcpy(mac_addr, pwdev_priv->pno_mac_addr, ETH_ALEN);
1582
if (mac_addr[0] == 0xFF) return;
1583
rtw_hal_random_gen_mac_addr(mac_addr);
1584
memcpy(pwdev_priv->pno_mac_addr, mac_addr, ETH_ALEN);
1585
#ifdef CONFIG_RTW_DEBUG
1586
print_hex_dump(KERN_DEBUG, "pno_mac_addr: ",
1587
DUMP_PREFIX_OFFSET, 16, 1, pwdev_priv->pno_mac_addr,
1588
ETH_ALEN, 1);
1589
#endif
1590
}
1591
1592
void rtw_hal_set_hw_mac_addr(PADAPTER adapter, u8 *mac_addr)
1593
{
1594
rtw_ps_deny(adapter, PS_DENY_IOCTL);
1595
LeaveAllPowerSaveModeDirect(adapter);
1596
1597
rtw_hal_set_hwreg(adapter, HW_VAR_MAC_ADDR, mac_addr);
1598
#ifdef CONFIG_RTW_DEBUG
1599
rtw_hal_dump_macaddr(RTW_DBGDUMP, adapter);
1600
#endif
1601
rtw_ps_deny_cancel(adapter, PS_DENY_IOCTL);
1602
}
1603
1604
static int rtw_cfgvendor_set_rand_mac_oui(struct wiphy *wiphy,
1605
struct wireless_dev *wdev, const void *data, int len)
1606
{
1607
int err = 0;
1608
PADAPTER adapter;
1609
void *devaddr;
1610
struct net_device *netdev;
1611
int type, mac_len;
1612
u8 pno_random_mac_oui[3];
1613
u8 mac_addr[ETH_ALEN] = {0};
1614
struct pwrctrl_priv *pwrctl;
1615
struct rtw_wdev_priv *pwdev_priv;
1616
1617
type = nla_type(data);
1618
mac_len = nla_len(data);
1619
if (mac_len != 3) {
1620
RTW_ERR("%s oui len error %d != 3\n", __func__, mac_len);
1621
return -1;
1622
}
1623
1624
if (type == ANDR_WIFI_ATTRIBUTE_RANDOM_MAC_OUI) {
1625
memcpy(pno_random_mac_oui, nla_data(data), 3);
1626
print_hex_dump(KERN_DEBUG, "pno_random_mac_oui: ",
1627
DUMP_PREFIX_OFFSET, 16, 1, pno_random_mac_oui,
1628
3, 1);
1629
1630
if (ETHER_ISMULTI(pno_random_mac_oui)) {
1631
pr_err("%s: oui is multicast address\n", __func__);
1632
return -1;
1633
}
1634
1635
adapter = wiphy_to_adapter(wiphy);
1636
if (adapter == NULL) {
1637
pr_err("%s: wiphy_to_adapter == NULL\n", __func__);
1638
return -1;
1639
}
1640
1641
pwdev_priv = adapter_wdev_data(adapter);
1642
1643
memcpy(mac_addr, pno_random_mac_oui, 3);
1644
rtw_hal_random_gen_mac_addr(mac_addr);
1645
memcpy(pwdev_priv->pno_mac_addr, mac_addr, ETH_ALEN);
1646
#ifdef CONFIG_RTW_DEBUG
1647
print_hex_dump(KERN_DEBUG, "pno_mac_addr: ",
1648
DUMP_PREFIX_OFFSET, 16, 1, pwdev_priv->pno_mac_addr,
1649
ETH_ALEN, 1);
1650
#endif
1651
} else {
1652
RTW_ERR("%s oui type error %x != 0x2\n", __func__, type);
1653
err = -1;
1654
}
1655
1656
1657
return err;
1658
}
1659
1660
#endif
1661
1662
1663
static int rtw_cfgvendor_set_nodfs_flag(struct wiphy *wiphy,
1664
struct wireless_dev *wdev, const void *data, int len)
1665
{
1666
int err = 0;
1667
int type;
1668
u32 nodfs = 0;
1669
_adapter *padapter = GET_PRIMARY_ADAPTER(wiphy_to_adapter(wiphy));
1670
1671
RTW_DBG(FUNC_NDEV_FMT" %s\n", FUNC_NDEV_ARG(wdev_to_ndev(wdev)), (char*)data);
1672
1673
type = nla_type(data);
1674
if (type == ANDR_WIFI_ATTRIBUTE_NODFS_SET) {
1675
nodfs = nla_get_u32(data);
1676
adapter_to_dvobj(padapter)->nodfs = nodfs;
1677
} else {
1678
err = -EINVAL;
1679
}
1680
1681
RTW_INFO("%s nodfs=%d, err=%d\n", __func__, nodfs, err);
1682
1683
return err;
1684
}
1685
1686
static int rtw_cfgvendor_set_country(struct wiphy *wiphy,
1687
struct wireless_dev *wdev, const void *data, int len)
1688
{
1689
#define CNTRY_BUF_SZ 4 /* Country string is 3 bytes + NUL */
1690
int err = 0, rem, type;
1691
char country_code[CNTRY_BUF_SZ] = {0};
1692
const struct nlattr *iter;
1693
_adapter *padapter = GET_PRIMARY_ADAPTER(wiphy_to_adapter(wiphy));
1694
1695
RTW_DBG(FUNC_NDEV_FMT" %s\n", FUNC_NDEV_ARG(wdev_to_ndev(wdev)), (char*)data);
1696
1697
nla_for_each_attr(iter, data, len, rem) {
1698
type = nla_type(iter);
1699
switch (type) {
1700
case ANDR_WIFI_ATTRIBUTE_COUNTRY:
1701
_rtw_memcpy(country_code, nla_data(iter),
1702
MIN(nla_len(iter), CNTRY_BUF_SZ));
1703
break;
1704
default:
1705
RTW_ERR("Unknown type: %d\n", type);
1706
return -EINVAL;
1707
}
1708
}
1709
1710
RTW_INFO("%s country_code:\"%c%c\" \n", __func__, country_code[0], country_code[1]);
1711
1712
rtw_set_country(padapter, country_code);
1713
1714
return err;
1715
}
1716
1717
static int rtw_cfgvendor_set_nd_offload(struct wiphy *wiphy,
1718
struct wireless_dev *wdev, const void *data, int len)
1719
{
1720
int err = 0;
1721
int type;
1722
u8 nd_en = 0;
1723
_adapter *padapter = GET_PRIMARY_ADAPTER(wiphy_to_adapter(wiphy));
1724
1725
RTW_DBG(FUNC_NDEV_FMT" %s\n", FUNC_NDEV_ARG(wdev_to_ndev(wdev)), (char*)data);
1726
1727
type = nla_type(data);
1728
if (type == ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE) {
1729
nd_en = nla_get_u8(data);
1730
/* ND has been enabled when wow is enabled */
1731
} else {
1732
err = -EINVAL;
1733
}
1734
1735
RTW_INFO("%s nd_en=%d, err=%d\n", __func__, nd_en, err);
1736
1737
return err;
1738
}
1739
#endif /* CONFIG_RTW_WIFI_HAL */
1740
1741
static const struct wiphy_vendor_command rtw_vendor_cmds[] = {
1742
#if defined(GSCAN_SUPPORT) && 0
1743
{
1744
{
1745
.vendor_id = OUI_GOOGLE,
1746
.subcmd = GSCAN_SUBCMD_GET_CAPABILITIES
1747
},
1748
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1749
.doit = rtw_cfgvendor_gscan_get_capabilities
1750
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1751
,
1752
.policy = VENDOR_CMD_RAW_DATA,
1753
.maxattr = 1
1754
#endif
1755
},
1756
{
1757
{
1758
.vendor_id = OUI_GOOGLE,
1759
.subcmd = GSCAN_SUBCMD_SET_CONFIG
1760
},
1761
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1762
.doit = rtw_cfgvendor_set_scan_cfg
1763
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1764
,
1765
.policy = VENDOR_CMD_RAW_DATA,
1766
.maxattr = 1
1767
#endif
1768
},
1769
{
1770
{
1771
.vendor_id = OUI_GOOGLE,
1772
.subcmd = GSCAN_SUBCMD_SET_SCAN_CONFIG
1773
},
1774
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1775
.doit = rtw_cfgvendor_set_batch_scan_cfg
1776
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1777
,
1778
.policy = VENDOR_CMD_RAW_DATA,
1779
.maxattr = 1
1780
#endif
1781
},
1782
{
1783
{
1784
.vendor_id = OUI_GOOGLE,
1785
.subcmd = GSCAN_SUBCMD_ENABLE_GSCAN
1786
},
1787
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1788
.doit = rtw_cfgvendor_initiate_gscan
1789
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1790
,
1791
.policy = VENDOR_CMD_RAW_DATA,
1792
.maxattr = 1
1793
#endif
1794
},
1795
{
1796
{
1797
.vendor_id = OUI_GOOGLE,
1798
.subcmd = GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS
1799
},
1800
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1801
.doit = rtw_cfgvendor_enable_full_scan_result
1802
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1803
,
1804
.policy = VENDOR_CMD_RAW_DATA,
1805
.maxattr = 1
1806
#endif
1807
},
1808
{
1809
{
1810
.vendor_id = OUI_GOOGLE,
1811
.subcmd = GSCAN_SUBCMD_SET_HOTLIST
1812
},
1813
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1814
.doit = rtw_cfgvendor_hotlist_cfg
1815
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1816
,
1817
.policy = VENDOR_CMD_RAW_DATA,
1818
.maxattr = 1
1819
#endif
1820
},
1821
{
1822
{
1823
.vendor_id = OUI_GOOGLE,
1824
.subcmd = GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG
1825
},
1826
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1827
.doit = rtw_cfgvendor_significant_change_cfg
1828
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1829
,
1830
.policy = VENDOR_CMD_RAW_DATA,
1831
.maxattr = 1
1832
#endif
1833
},
1834
{
1835
{
1836
.vendor_id = OUI_GOOGLE,
1837
.subcmd = GSCAN_SUBCMD_GET_SCAN_RESULTS
1838
},
1839
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1840
.doit = rtw_cfgvendor_gscan_get_batch_results
1841
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1842
,
1843
.policy = VENDOR_CMD_RAW_DATA,
1844
.maxattr = 1
1845
#endif
1846
},
1847
{
1848
{
1849
.vendor_id = OUI_GOOGLE,
1850
.subcmd = GSCAN_SUBCMD_GET_CHANNEL_LIST
1851
},
1852
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1853
.doit = rtw_cfgvendor_gscan_get_channel_list
1854
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1855
,
1856
.policy = VENDOR_CMD_RAW_DATA,
1857
.maxattr = 1
1858
#endif
1859
},
1860
#endif /* GSCAN_SUPPORT */
1861
#if defined(RTT_SUPPORT) && 0
1862
{
1863
{
1864
.vendor_id = OUI_GOOGLE,
1865
.subcmd = RTT_SUBCMD_SET_CONFIG
1866
},
1867
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1868
.doit = rtw_cfgvendor_rtt_set_config
1869
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1870
,
1871
.policy = VENDOR_CMD_RAW_DATA,
1872
.maxattr = 1
1873
#endif
1874
},
1875
{
1876
{
1877
.vendor_id = OUI_GOOGLE,
1878
.subcmd = RTT_SUBCMD_CANCEL_CONFIG
1879
},
1880
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1881
.doit = rtw_cfgvendor_rtt_cancel_config
1882
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1883
,
1884
.policy = VENDOR_CMD_RAW_DATA,
1885
.maxattr = 1
1886
#endif
1887
},
1888
{
1889
{
1890
.vendor_id = OUI_GOOGLE,
1891
.subcmd = RTT_SUBCMD_GETCAPABILITY
1892
},
1893
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1894
.doit = rtw_cfgvendor_rtt_get_capability
1895
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1896
,
1897
.policy = VENDOR_CMD_RAW_DATA,
1898
.maxattr = 1
1899
#endif
1900
},
1901
#endif /* RTT_SUPPORT */
1902
#ifdef CONFIG_RTW_CFGVEDNOR_LLSTATS
1903
{
1904
{
1905
.vendor_id = OUI_GOOGLE,
1906
.subcmd = LSTATS_SUBCMD_GET_INFO
1907
},
1908
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1909
.doit = rtw_cfgvendor_lstats_get_info
1910
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1911
,
1912
.policy = VENDOR_CMD_RAW_DATA,
1913
.maxattr = 1
1914
#endif
1915
},
1916
{
1917
{
1918
.vendor_id = OUI_GOOGLE,
1919
.subcmd = LSTATS_SUBCMD_SET_INFO
1920
},
1921
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1922
.doit = rtw_cfgvendor_lstats_set_info
1923
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1924
,
1925
.policy = VENDOR_CMD_RAW_DATA,
1926
.maxattr = 1
1927
#endif
1928
},
1929
{
1930
{
1931
.vendor_id = OUI_GOOGLE,
1932
.subcmd = LSTATS_SUBCMD_CLEAR_INFO
1933
},
1934
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1935
.doit = rtw_cfgvendor_lstats_clear_info
1936
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1937
,
1938
.policy = VENDOR_CMD_RAW_DATA,
1939
.maxattr = 1
1940
#endif
1941
},
1942
#endif /* CONFIG_RTW_CFGVEDNOR_LLSTATS */
1943
#ifdef CONFIG_RTW_CFGVEDNOR_RSSIMONITOR
1944
{
1945
{
1946
.vendor_id = OUI_GOOGLE,
1947
.subcmd = WIFI_SUBCMD_SET_RSSI_MONITOR
1948
},
1949
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1950
.doit = rtw_cfgvendor_set_rssi_monitor
1951
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1952
,
1953
.policy = VENDOR_CMD_RAW_DATA,
1954
.maxattr = 1
1955
#endif
1956
},
1957
#endif /* CONFIG_RTW_CFGVEDNOR_RSSIMONITOR */
1958
#ifdef CONFIG_RTW_CFGVENDOR_WIFI_LOGGER
1959
{
1960
{
1961
.vendor_id = OUI_GOOGLE,
1962
.subcmd = LOGGER_START_LOGGING
1963
},
1964
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1965
.doit = rtw_cfgvendor_logger_start_logging
1966
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1967
,
1968
.policy = VENDOR_CMD_RAW_DATA,
1969
.maxattr = 1
1970
#endif
1971
},
1972
{
1973
{
1974
.vendor_id = OUI_GOOGLE,
1975
.subcmd = LOGGER_GET_FEATURE
1976
},
1977
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1978
.doit = rtw_cfgvendor_logger_get_feature
1979
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1980
,
1981
.policy = VENDOR_CMD_RAW_DATA,
1982
.maxattr = 1
1983
#endif
1984
},
1985
{
1986
{
1987
.vendor_id = OUI_GOOGLE,
1988
.subcmd = LOGGER_GET_VER
1989
},
1990
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
1991
.doit = rtw_cfgvendor_logger_get_version
1992
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
1993
,
1994
.policy = VENDOR_CMD_RAW_DATA,
1995
.maxattr = 1
1996
#endif
1997
},
1998
{
1999
{
2000
.vendor_id = OUI_GOOGLE,
2001
.subcmd = LOGGER_GET_RING_STATUS
2002
},
2003
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2004
.doit = rtw_cfgvendor_logger_get_ring_status
2005
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
2006
,
2007
.policy = VENDOR_CMD_RAW_DATA,
2008
.maxattr = 1
2009
#endif
2010
},
2011
{
2012
{
2013
.vendor_id = OUI_GOOGLE,
2014
.subcmd = LOGGER_GET_RING_DATA
2015
},
2016
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2017
.doit = rtw_cfgvendor_logger_get_ring_data
2018
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
2019
,
2020
.policy = VENDOR_CMD_RAW_DATA,
2021
.maxattr = 1
2022
#endif
2023
},
2024
{
2025
{
2026
.vendor_id = OUI_GOOGLE,
2027
.subcmd = LOGGER_TRIGGER_MEM_DUMP
2028
},
2029
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2030
.doit = rtw_cfgvendor_logger_get_firmware_memory_dump
2031
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
2032
,
2033
.policy = VENDOR_CMD_RAW_DATA,
2034
.maxattr = 1
2035
#endif
2036
},
2037
{
2038
{
2039
.vendor_id = OUI_GOOGLE,
2040
.subcmd = LOGGER_START_PKT_FATE_MONITORING
2041
},
2042
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2043
.doit = rtw_cfgvendor_logger_start_pkt_fate_monitoring
2044
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
2045
,
2046
.policy = VENDOR_CMD_RAW_DATA,
2047
.maxattr = 1
2048
#endif
2049
},
2050
{
2051
{
2052
.vendor_id = OUI_GOOGLE,
2053
.subcmd = LOGGER_GET_TX_PKT_FATES
2054
},
2055
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2056
.doit = rtw_cfgvendor_logger_get_tx_pkt_fates
2057
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
2058
,
2059
.policy = VENDOR_CMD_RAW_DATA,
2060
.maxattr = 1
2061
#endif
2062
},
2063
{
2064
{
2065
.vendor_id = OUI_GOOGLE,
2066
.subcmd = LOGGER_GET_RX_PKT_FATES
2067
},
2068
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2069
.doit = rtw_cfgvendor_logger_get_rx_pkt_fates
2070
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
2071
,
2072
.policy = VENDOR_CMD_RAW_DATA,
2073
.maxattr = 1
2074
#endif
2075
},
2076
#endif /* CONFIG_RTW_CFGVENDOR_WIFI_LOGGER */
2077
#ifdef CONFIG_RTW_WIFI_HAL
2078
#ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI
2079
{
2080
{
2081
.vendor_id = OUI_GOOGLE,
2082
.subcmd = WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI
2083
},
2084
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2085
.doit = rtw_cfgvendor_set_rand_mac_oui
2086
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
2087
,
2088
.policy = VENDOR_CMD_RAW_DATA,
2089
.maxattr = 1
2090
#endif
2091
},
2092
#endif
2093
{
2094
{
2095
.vendor_id = OUI_GOOGLE,
2096
.subcmd = WIFI_SUBCMD_NODFS_SET
2097
},
2098
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2099
.doit = rtw_cfgvendor_set_nodfs_flag
2100
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
2101
,
2102
.policy = VENDOR_CMD_RAW_DATA,
2103
.maxattr = 1
2104
#endif
2105
},
2106
{
2107
{
2108
.vendor_id = OUI_GOOGLE,
2109
.subcmd = WIFI_SUBCMD_SET_COUNTRY_CODE
2110
},
2111
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2112
.doit = rtw_cfgvendor_set_country
2113
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
2114
,
2115
.policy = VENDOR_CMD_RAW_DATA,
2116
.maxattr = 1
2117
#endif
2118
},
2119
{
2120
{
2121
.vendor_id = OUI_GOOGLE,
2122
.subcmd = WIFI_SUBCMD_CONFIG_ND_OFFLOAD
2123
},
2124
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2125
.doit = rtw_cfgvendor_set_nd_offload
2126
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
2127
,
2128
.policy = VENDOR_CMD_RAW_DATA,
2129
.maxattr = 1
2130
#endif
2131
},
2132
#endif /* CONFIG_RTW_WIFI_HAL */
2133
{
2134
{
2135
.vendor_id = OUI_GOOGLE,
2136
.subcmd = WIFI_SUBCMD_GET_FEATURE_SET
2137
},
2138
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2139
.doit = rtw_cfgvendor_get_feature_set
2140
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
2141
,
2142
.policy = VENDOR_CMD_RAW_DATA,
2143
.maxattr = 1
2144
#endif
2145
},
2146
{
2147
{
2148
.vendor_id = OUI_GOOGLE,
2149
.subcmd = WIFI_SUBCMD_GET_FEATURE_SET_MATRIX
2150
},
2151
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
2152
.doit = rtw_cfgvendor_get_feature_set_matrix
2153
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
2154
,
2155
.policy = VENDOR_CMD_RAW_DATA,
2156
.maxattr = 1
2157
#endif
2158
}
2159
};
2160
2161
static const struct nl80211_vendor_cmd_info rtw_vendor_events[] = {
2162
#if defined(GSCAN_SUPPORT) && 0
2163
{ OUI_GOOGLE, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS },
2164
{ OUI_GOOGLE, GSCAN_EVENT_HOTLIST_RESULTS_FOUND },
2165
{ OUI_GOOGLE, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE },
2166
{ OUI_GOOGLE, GSCAN_EVENT_FULL_SCAN_RESULTS },
2167
#endif /* GSCAN_SUPPORT */
2168
#if defined(RTT_SUPPORT) && 0
2169
{ OUI_GOOGLE, RTT_EVENT_COMPLETE },
2170
#endif /* RTT_SUPPORT */
2171
2172
#ifdef CONFIG_RTW_CFGVEDNOR_RSSIMONITOR
2173
{ OUI_GOOGLE, GOOGLE_RSSI_MONITOR_EVENT },
2174
#endif /* RTW_CFGVEDNOR_RSSIMONITR */
2175
2176
#if defined(GSCAN_SUPPORT) && 0
2177
{ OUI_GOOGLE, GSCAN_EVENT_COMPLETE_SCAN },
2178
{ OUI_GOOGLE, GSCAN_EVENT_HOTLIST_RESULTS_LOST }
2179
#endif /* GSCAN_SUPPORT */
2180
};
2181
2182
int rtw_cfgvendor_attach(struct wiphy *wiphy)
2183
{
2184
2185
RTW_INFO("Register RTW cfg80211 vendor cmd(0x%x) interface\n", NL80211_CMD_VENDOR);
2186
2187
wiphy->vendor_commands = rtw_vendor_cmds;
2188
wiphy->n_vendor_commands = ARRAY_SIZE(rtw_vendor_cmds);
2189
wiphy->vendor_events = rtw_vendor_events;
2190
wiphy->n_vendor_events = ARRAY_SIZE(rtw_vendor_events);
2191
2192
return 0;
2193
}
2194
2195
int rtw_cfgvendor_detach(struct wiphy *wiphy)
2196
{
2197
RTW_INFO("Vendor: Unregister RTW cfg80211 vendor interface\n");
2198
2199
wiphy->vendor_commands = NULL;
2200
wiphy->vendor_events = NULL;
2201
wiphy->n_vendor_commands = 0;
2202
wiphy->n_vendor_events = 0;
2203
2204
return 0;
2205
}
2206
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(RTW_VENDOR_EXT_SUPPORT) */
2207
2208
#endif /* CONFIG_IOCTL_CFG80211 */
2209
2210