-
-
Notifications
You must be signed in to change notification settings - Fork 7
/
dhd_rtt.c
5525 lines (5013 loc) · 164 KB
/
dhd_rtt.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* Broadcom Dongle Host Driver (DHD), RTT
*
* Copyright (C) 2022, Broadcom.
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
* under the terms of the GNU General Public License version 2 (the "GPL"),
* available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
*
* As a special exception, the copyright holders of this software give you
* permission to link this software with independent modules, and to copy and
* distribute the resulting executable under terms of your choice, provided that
* you also meet, for each linked independent module, the terms and conditions of
* the license of that module. An independent module is a module which is not
* derived from this software. The special exception does not apply to any
* modifications of the software.
*
*
* <<Broadcom-WL-IPTag/Dual:>>
*/
#include <typedefs.h>
#include <osl.h>
#include <epivers.h>
#include <bcmutils.h>
#include <bcmendian.h>
#include <linuxver.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/sort.h>
#include <dngl_stats.h>
#include <wlioctl.h>
#include <bcmwifi_rspec.h>
#include <bcmevent.h>
#include <dhd.h>
#include <dhd_rtt.h>
#include <dhd_dbg.h>
#include <dhd_bus.h>
#include <wldev_common.h>
#ifdef WL_CFG80211
#include <wl_cfg80211.h>
#endif /* WL_CFG80211 */
#ifdef WL_NAN
#include <wl_cfgnan.h>
#endif /* WL_NAN */
#ifdef CUSTOM_PREFIX
#define RTT_PRINT_PREFIX "[%s]"CUSTOM_PREFIX, OSL_GET_RTCTIME()
#define RTT_PRINT_SYSTEM_TIME pr_cont(RTT_PRINT_PREFIX)
#define RTT_CONS_ONLY(args) \
do { \
RTT_PRINT_SYSTEM_TIME; \
pr_cont args; \
} while (0)
#else
#define RTT_PRINT_SYSTEM_TIME
#define RTT_CONS_ONLY(args) do { printf args;} while (0)
#endif /* CUSTOM_PREFIX */
static DEFINE_SPINLOCK(noti_list_lock);
#define NULL_CHECK(p, s, err) \
do { \
if (!(p)) { \
RTT_CONS_ONLY(("NULL POINTER (%s) : %s\n", __FUNCTION__, (s))); \
err = BCME_ERROR; \
return err; \
} \
} while (0)
#define DHD_RTT_CHK_SET_PARAM(param, param_cnt, targets, tlvid) \
do { \
if ((param_cnt) >= FTM_MAX_PARAMS) { \
DHD_RTT_ERR(("Param cnt exceeded for FTM cfg iovar\n")); \
err = BCME_ERROR; \
goto exit; \
} else { \
dhd_rtt_set_ftm_config_param((param), &(param_cnt), \
(targets), (tlvid)); \
}\
} while (0)
#define TIMESPEC64_TO_US(ts) (((ts).tv_sec * USEC_PER_SEC) + \
(ts).tv_nsec / NSEC_PER_USEC)
#undef DHD_RTT_MEM
#undef DHD_RTT_ERR
#define DHD_RTT_MEM DHD_LOG_MEM
#define DHD_RTT_ERR DHD_ERROR
#define FTM_IOC_BUFSZ 2048 /* ioc buffsize for our module (> BCM_XTLV_HDR_SIZE) */
#define FTM_AVAIL_MAX_SLOTS 32
#define FTM_MAX_CONFIGS 10
#define FTM_MAX_PARAMS 20
#define FTM_DEFAULT_SESSION 1
#define FTM_BURST_TIMEOUT_UNIT 250 /* 250 ns */
#define FTM_INVALID -1
#define FTM_DEFAULT_CNT_20M 24u
#define FTM_DEFAULT_CNT_40M 16u
#define FTM_DEFAULT_CNT_80M 11u
#define FTM_DEFAULT_CNT_160M 5u
/* To handle congestion env, set max dur/timeout */
#define FTM_MAX_BURST_DUR_TMO_MS 128u
/* convenience macros */
#define FTM_TU2MICRO(_tu) ((uint64)(_tu) << 10)
#define FTM_MICRO2TU(_tu) ((uint64)(_tu) >> 10)
#define FTM_TU2MILLI(_tu) ((uint32)FTM_TU2MICRO(_tu) / 1000)
#define FTM_MICRO2MILLI(_x) ((uint32)(_x) / 1000)
#define FTM_MICRO2SEC(_x) ((uint32)(_x) / 1000000)
#define FTM_INTVL2NSEC(_intvl) ((uint32)ftm_intvl2nsec(_intvl))
#define FTM_INTVL2USEC(_intvl) ((uint32)ftm_intvl2usec(_intvl))
#define FTM_INTVL2MSEC(_intvl) (FTM_INTVL2USEC(_intvl) / 1000)
#define FTM_INTVL2SEC(_intvl) (FTM_INTVL2USEC(_intvl) / 1000000)
#define FTM_USECIN100MILLI(_usec) ((_usec) / 100000)
/* broadcom specific set to have more accurate data */
#define ENABLE_VHT_ACK
#define CH_MIN_5G_CHANNEL 34
/* CUR ETH became obsolete with this major version onwards */
#define RTT_IOV_CUR_ETH_OBSOLETE 12
/*
* Parallel RTT Sessions are supported
* with this major and minor verion onwards
*/
#define RTT_PARALLEL_SSNS_SUPPORTED_MAJ_VER 14
#define RTT_PARALLEL_SSNS_SUPPORTED_MIN_VER 2
/* PROXD TIMEOUT */
#define DHD_RTT_TIMER_INTERVAL_MS 5000u
#define DHD_NAN_RTT_TIMER_INTERVAL_MS 20000u
#define DHD_NAN_RTT_MAX_SESSIONS 4u
#define DHD_NAN_RTT_MAX_SESSIONS_LEGACY 1u
struct rtt_noti_callback {
struct list_head list;
void *ctx;
dhd_rtt_compl_noti_fn noti_fn;
};
/* bitmask indicating which command groups; */
typedef enum {
FTM_SUBCMD_FLAG_METHOD = 0x01, /* FTM method command */
FTM_SUBCMD_FLAG_SESSION = 0x02, /* FTM session command */
FTM_SUBCMD_FLAG_ALL = FTM_SUBCMD_FLAG_METHOD | FTM_SUBCMD_FLAG_SESSION
} ftm_subcmd_flag_t;
/* proxd ftm config-category definition */
typedef enum {
FTM_CONFIG_CAT_GENERAL = 1, /* generial configuration */
FTM_CONFIG_CAT_OPTIONS = 2, /* 'config options' */
FTM_CONFIG_CAT_AVAIL = 3, /* 'config avail' */
} ftm_config_category_t;
typedef struct ftm_subcmd_info {
int16 version; /* FTM version (optional) */
char *name; /* cmd-name string as cmdline input */
wl_proxd_cmd_t cmdid; /* cmd-id */
bcm_xtlv_unpack_cbfn_t *handler; /* cmd response handler (optional) */
ftm_subcmd_flag_t cmdflag; /* CMD flag (optional) */
} ftm_subcmd_info_t;
typedef struct ftm_config_options_info {
uint32 flags; /* wl_proxd_flags_t/wl_proxd_session_flags_t */
bool enable;
} ftm_config_options_info_t;
typedef struct ftm_config_param_info {
uint16 tlvid; /* mapping TLV id for the item */
union {
uint32 chanspec;
struct ether_addr mac_addr;
wl_proxd_intvl_t data_intvl;
uint32 data32;
uint16 data16;
uint8 data8;
uint32 event_mask;
};
} ftm_config_param_info_t;
/*
* definition for id-string mapping.
* This is used to map an id (can be cmd-id, tlv-id, ....) to a text-string
* for debug-display or cmd-log-display
*/
typedef struct ftm_strmap_entry {
int32 id;
char *text;
} ftm_strmap_entry_t;
typedef struct ftm_status_map_host_entry {
wl_proxd_status_t proxd_status;
rtt_reason_t rtt_reason;
} ftm_status_map_host_entry_t;
typedef struct rtt_event_data_info {
wl_proxd_ftm_session_status_t *session_status;
rtt_result_t *rtt_result;
bcm_xtlv_t *tlv;
} rtt_event_data_info_t;
static uint16
rtt_result_ver(uint16 tlvid, const uint8 *p_data);
static int
dhd_rtt_convert_results_to_host_v1(rtt_result_t *rtt_result, const uint8 *p_data,
uint16 tlvid, uint16 len);
static int
dhd_rtt_convert_results_to_host_v2(rtt_result_t *rtt_result, const uint8 *p_data,
uint16 tlvid, uint16 len);
static int
dhd_rtt_convert_results_to_host_v3(rtt_result_t *rtt_result, const uint8 *p_data,
uint16 tlvid, uint16 len);
static wifi_rate_v1
dhd_rtt_convert_rate_to_host(uint32 ratespec);
#if defined(WL_CFG80211) && defined(RTT_DEBUG)
const char *
ftm_cmdid_to_str(uint16 cmdid);
#endif /* WL_CFG80211 && RTT_DEBUG */
#ifdef WL_CFG80211
static int
dhd_rtt_start(dhd_pub_t *dhd);
static int dhd_rtt_create_failure_result(rtt_status_info_t *rtt_status,
struct ether_addr *addr);
static void dhd_rtt_handle_rtt_session_end(dhd_pub_t *dhd);
static void dhd_rtt_timeout_work(struct work_struct *work);
static bool dhd_rtt_get_report_header(rtt_status_info_t *rtt_status,
rtt_results_header_t **rtt_results_header, struct ether_addr *addr);
static void dhd_rtt_set_ftm_config_param(ftm_config_param_info_t *ftm_params,
int *ftm_param_cnt, rtt_target_info_t *rtt_target, uint16 tlvid);
static int dhd_rtt_ftm_config(dhd_pub_t *dhd, wl_proxd_session_id_t session_id,
void *ftm_cfg_opt, int ftm_cfg_opt_cnt, void *ftm_cfg_gen, int ftm_cfg_gen_cnt);
#ifdef WL_NAN
static void dhd_rtt_trigger_pending_targets_on_session_end(dhd_pub_t *dhd);
#endif /* WL_NAN */
#endif /* WL_CFG80211 */
static const int burst_duration_idx[] = {0, 0, 1, 2, 4, 8, 16, 32, 64, 128, 0, 0};
/* ftm status mapping to host status */
static const ftm_status_map_host_entry_t ftm_status_map_info[] = {
{WL_PROXD_E_INCOMPLETE, RTT_STATUS_FAILURE},
{WL_PROXD_E_OVERRIDDEN, RTT_STATUS_FAILURE},
{WL_PROXD_E_ASAP_FAILED, RTT_STATUS_FAILURE},
{WL_PROXD_E_NOTSTARTED, RTT_STATUS_FAIL_NOT_SCHEDULED_YET},
{WL_PROXD_E_INVALIDMEAS, RTT_STATUS_FAIL_INVALID_TS},
{WL_PROXD_E_INCAPABLE, RTT_STATUS_FAIL_NO_CAPABILITY},
{WL_PROXD_E_MISMATCH, RTT_STATUS_FAILURE},
{WL_PROXD_E_DUP_SESSION, RTT_STATUS_FAILURE},
{WL_PROXD_E_REMOTE_FAIL, RTT_STATUS_FAILURE},
{WL_PROXD_E_REMOTE_INCAPABLE, RTT_STATUS_FAILURE},
{WL_PROXD_E_SCHED_FAIL, RTT_STATUS_FAIL_SCHEDULE},
{WL_PROXD_E_PROTO, RTT_STATUS_FAIL_PROTOCOL},
{WL_PROXD_E_EXPIRED, RTT_STATUS_FAILURE},
{WL_PROXD_E_TIMEOUT, RTT_STATUS_FAIL_TM_TIMEOUT},
{WL_PROXD_E_NOACK, RTT_STATUS_FAIL_NO_RSP},
{WL_PROXD_E_DEFERRED, RTT_STATUS_FAILURE},
{WL_PROXD_E_INVALID_SID, RTT_STATUS_FAILURE},
{WL_PROXD_E_REMOTE_CANCEL, RTT_STATUS_FAILURE},
{WL_PROXD_E_CANCELED, RTT_STATUS_ABORTED},
{WL_PROXD_E_INVALID_SESSION, RTT_STATUS_FAILURE},
{WL_PROXD_E_BAD_STATE, RTT_STATUS_FAILURE},
{WL_PROXD_E_ERROR, RTT_STATUS_FAILURE},
{WL_PROXD_E_OK, RTT_STATUS_SUCCESS}
};
static const ftm_strmap_entry_t ftm_event_type_loginfo[] = {
/* wl_proxd_event_type_t, text-string */
{ WL_PROXD_EVENT_NONE, "none" },
{ WL_PROXD_EVENT_SESSION_CREATE, "session create" },
{ WL_PROXD_EVENT_SESSION_START, "session start" },
{ WL_PROXD_EVENT_FTM_REQ, "FTM req" },
{ WL_PROXD_EVENT_BURST_START, "burst start" },
{ WL_PROXD_EVENT_BURST_END, "burst end" },
{ WL_PROXD_EVENT_SESSION_END, "session end" },
{ WL_PROXD_EVENT_SESSION_RESTART, "session restart" },
{ WL_PROXD_EVENT_BURST_RESCHED, "burst rescheduled" },
{ WL_PROXD_EVENT_SESSION_DESTROY, "session destroy" },
{ WL_PROXD_EVENT_RANGE_REQ, "range request" },
{ WL_PROXD_EVENT_FTM_FRAME, "FTM frame" },
{ WL_PROXD_EVENT_DELAY, "delay" },
{ WL_PROXD_EVENT_VS_INITIATOR_RPT, "initiator-report " }, /* rx initiator-rpt */
{ WL_PROXD_EVENT_RANGING, "ranging " },
#ifdef WL_RTT_LCI
{ WL_PROXD_EVENT_LCI_MEAS_REP, "lci report" },
{ WL_PROXD_EVENT_CIVIC_MEAS_REP, "civic report" },
#endif /* WL_RTT_LCI */
{ WL_PROXD_EVENT_COLLECT, "collect" },
{ WL_PROXD_EVENT_MF_STATS, "mf_stats" },
{ WL_PROXD_EVENT_START_WAIT, "start-wait"}
};
/*
* session-state --> text string mapping
*/
static const ftm_strmap_entry_t ftm_session_state_value_loginfo[] = {
/* wl_proxd_session_state_t, text string */
{ WL_PROXD_SESSION_STATE_CREATED, "created" },
{ WL_PROXD_SESSION_STATE_CONFIGURED, "configured" },
{ WL_PROXD_SESSION_STATE_STARTED, "started" },
{ WL_PROXD_SESSION_STATE_DELAY, "delay" },
{ WL_PROXD_SESSION_STATE_USER_WAIT, "user-wait" },
{ WL_PROXD_SESSION_STATE_SCHED_WAIT, "sched-wait" },
{ WL_PROXD_SESSION_STATE_BURST, "burst" },
{ WL_PROXD_SESSION_STATE_STOPPING, "stopping" },
{ WL_PROXD_SESSION_STATE_ENDED, "ended" },
{ WL_PROXD_SESSION_STATE_DESTROYING, "destroying" },
{ WL_PROXD_SESSION_STATE_NONE, "none" }
};
/*
* status --> text string mapping
*/
static const ftm_strmap_entry_t ftm_status_value_loginfo[] = {
/* wl_proxd_status_t, text-string */
{ WL_PROXD_E_OVERRIDDEN, "overridden" },
{ WL_PROXD_E_ASAP_FAILED, "ASAP failed" },
{ WL_PROXD_E_NOTSTARTED, "not started" },
{ WL_PROXD_E_INVALIDMEAS, "invalid measurement" },
{ WL_PROXD_E_INCAPABLE, "incapable" },
{ WL_PROXD_E_MISMATCH, "mismatch"},
{ WL_PROXD_E_DUP_SESSION, "dup session" },
{ WL_PROXD_E_REMOTE_FAIL, "remote fail" },
{ WL_PROXD_E_REMOTE_INCAPABLE, "remote incapable" },
{ WL_PROXD_E_SCHED_FAIL, "sched failure" },
{ WL_PROXD_E_PROTO, "protocol error" },
{ WL_PROXD_E_EXPIRED, "expired" },
{ WL_PROXD_E_TIMEOUT, "timeout" },
{ WL_PROXD_E_NOACK, "no ack" },
{ WL_PROXD_E_DEFERRED, "deferred" },
{ WL_PROXD_E_INVALID_SID, "invalid session id" },
{ WL_PROXD_E_REMOTE_CANCEL, "remote cancel" },
{ WL_PROXD_E_CANCELED, "canceled" },
{ WL_PROXD_E_INVALID_SESSION, "invalid session" },
{ WL_PROXD_E_BAD_STATE, "bad state" },
{ WL_PROXD_E_ERROR, "error" },
{ WL_PROXD_E_OK, "OK" }
};
/*
* time interval unit --> text string mapping
*/
static const ftm_strmap_entry_t ftm_tmu_value_loginfo[] = {
/* wl_proxd_tmu_t, text-string */
{ WL_PROXD_TMU_TU, "TU" },
{ WL_PROXD_TMU_SEC, "sec" },
{ WL_PROXD_TMU_MILLI_SEC, "ms" },
{ WL_PROXD_TMU_MICRO_SEC, "us" },
{ WL_PROXD_TMU_NANO_SEC, "ns" },
{ WL_PROXD_TMU_PICO_SEC, "ps" }
};
struct ieee_80211_mcs_rate_info {
uint8 constellation_bits;
uint8 coding_q;
uint8 coding_d;
};
static const struct ieee_80211_mcs_rate_info wl_mcs_info[] = {
{ 1, 1, 2 }, /* MCS 0: MOD: BPSK, CR 1/2 */
{ 2, 1, 2 }, /* MCS 1: MOD: QPSK, CR 1/2 */
{ 2, 3, 4 }, /* MCS 2: MOD: QPSK, CR 3/4 */
{ 4, 1, 2 }, /* MCS 3: MOD: 16QAM, CR 1/2 */
{ 4, 3, 4 }, /* MCS 4: MOD: 16QAM, CR 3/4 */
{ 6, 2, 3 }, /* MCS 5: MOD: 64QAM, CR 2/3 */
{ 6, 3, 4 }, /* MCS 6: MOD: 64QAM, CR 3/4 */
{ 6, 5, 6 }, /* MCS 7: MOD: 64QAM, CR 5/6 */
{ 8, 3, 4 }, /* MCS 8: MOD: 256QAM, CR 3/4 */
{ 8, 5, 6 } /* MCS 9: MOD: 256QAM, CR 5/6 */
};
/**
* Returns the rate in [Kbps] units for a caller supplied MCS/bandwidth/Nss/Sgi combination.
* 'mcs' : a *single* spatial stream MCS (11n or 11ac)
*/
uint
rate_mcs2rate(uint mcs, uint nss, uint bw, int sgi)
{
const int ksps = 250; /* kilo symbols per sec, 4 us sym */
const int Nsd_20MHz = 52;
const int Nsd_40MHz = 108;
const int Nsd_80MHz = 234;
const int Nsd_160MHz = 468;
uint rate;
if (mcs == 32) {
/* just return fixed values for mcs32 instead of trying to parametrize */
rate = (sgi == 0) ? 6000 : 6778;
} else if (mcs <= 9) {
/* This calculation works for 11n HT and 11ac VHT if the HT mcs values
* are decomposed into a base MCS = MCS % 8, and Nss = 1 + MCS / 8.
* That is, HT MCS 23 is a base MCS = 7, Nss = 3
*/
/* find the number of complex numbers per symbol */
if (RSPEC_IS20MHZ(bw)) {
/* 4360 TODO: eliminate Phy const in rspec bw, then just compare
* as in 80 and 160 case below instead of RSPEC_IS20MHZ(bw)
*/
rate = Nsd_20MHz;
} else if (RSPEC_IS40MHZ(bw)) {
/* 4360 TODO: eliminate Phy const in rspec bw, then just compare
* as in 80 and 160 case below instead of RSPEC_IS40MHZ(bw)
*/
rate = Nsd_40MHz;
} else if (bw == WL_RSPEC_BW_80MHZ) {
rate = Nsd_80MHz;
} else if (bw == WL_RSPEC_BW_160MHZ) {
rate = Nsd_160MHz;
} else {
rate = 0;
}
/* multiply by bits per number from the constellation in use */
rate = rate * wl_mcs_info[mcs].constellation_bits;
/* adjust for the number of spatial streams */
rate = rate * nss;
/* adjust for the coding rate given as a quotient and divisor */
rate = (rate * wl_mcs_info[mcs].coding_q) / wl_mcs_info[mcs].coding_d;
/* multiply by Kilo symbols per sec to get Kbps */
rate = rate * ksps;
/* adjust the symbols per sec for SGI
* symbol duration is 4 us without SGI, and 3.6 us with SGI,
* so ratio is 10 / 9
*/
if (sgi) {
/* add 4 for rounding of division by 9 */
rate = ((rate * 10) + 4) / 9;
}
} else {
rate = 0;
}
return rate;
} /* wlc_rate_mcs2rate */
/** take a well formed ratespec_t arg and return phy rate in [Kbps] units */
static uint32
rate_rspec2rate(uint32 rspec)
{
int rate = 0;
if (RSPEC_ISLEGACY(rspec)) {
rate = 500 * (rspec & WL_RSPEC_RATE_MASK);
} else if (RSPEC_ISHT(rspec)) {
uint mcs = (rspec & WL_RSPEC_RATE_MASK);
if (mcs == 32) {
rate = rate_mcs2rate(mcs, 1, WL_RSPEC_BW_40MHZ, RSPEC_ISSGI(rspec));
} else {
uint nss = 1 + (mcs / 8);
mcs = mcs % 8;
rate = rate_mcs2rate(mcs, nss, RSPEC_BW(rspec), RSPEC_ISSGI(rspec));
}
} else if (RSPEC_ISVHT(rspec)) {
uint mcs = (rspec & WL_RSPEC_VHT_MCS_MASK);
uint nss = (rspec & WL_RSPEC_VHT_NSS_MASK) >> WL_RSPEC_VHT_NSS_SHIFT;
if (mcs > 9 || nss > 8) {
DHD_RTT(("%s: Invalid mcs %d or nss %d\n", __FUNCTION__, mcs, nss));
goto exit;
}
rate = rate_mcs2rate(mcs, nss, RSPEC_BW(rspec), RSPEC_ISSGI(rspec));
} else {
DHD_RTT(("%s: wrong rspec:%d\n", __FUNCTION__, rspec));
}
exit:
return rate;
}
char resp_buf[WLC_IOCTL_SMLEN];
static uint64
ftm_intvl2nsec(const wl_proxd_intvl_t *intvl)
{
uint64 ret;
ret = intvl->intvl;
switch (intvl->tmu) {
case WL_PROXD_TMU_TU: ret = FTM_TU2MICRO(ret) * 1000; break;
case WL_PROXD_TMU_SEC: ret *= 1000000000; break;
case WL_PROXD_TMU_MILLI_SEC: ret *= 1000000; break;
case WL_PROXD_TMU_MICRO_SEC: ret *= 1000; break;
case WL_PROXD_TMU_PICO_SEC: ret = intvl->intvl / 1000; break;
case WL_PROXD_TMU_NANO_SEC: /* fall through */
default: break;
}
return ret;
}
uint64
ftm_intvl2usec(const wl_proxd_intvl_t *intvl)
{
uint64 ret;
ret = intvl->intvl;
switch (intvl->tmu) {
case WL_PROXD_TMU_TU: ret = FTM_TU2MICRO(ret); break;
case WL_PROXD_TMU_SEC: ret *= 1000000; break;
case WL_PROXD_TMU_NANO_SEC: ret = intvl->intvl / 1000; break;
case WL_PROXD_TMU_PICO_SEC: ret = intvl->intvl / 1000000; break;
case WL_PROXD_TMU_MILLI_SEC: ret *= 1000; break;
case WL_PROXD_TMU_MICRO_SEC: /* fall through */
default: break;
}
return ret;
}
/*
* lookup 'id' (as a key) from a fw status to host map table
* if found, return the corresponding reason code
*/
static rtt_reason_t
ftm_get_statusmap_info(wl_proxd_status_t id, const ftm_status_map_host_entry_t *p_table,
uint32 num_entries)
{
int i;
const ftm_status_map_host_entry_t *p_entry;
/* scan thru the table till end */
p_entry = p_table;
for (i = 0; i < (int) num_entries; i++)
{
if (p_entry->proxd_status == id) {
return p_entry->rtt_reason;
}
p_entry++; /* next entry */
}
return RTT_STATUS_FAILURE; /* not found */
}
/*
* lookup 'id' (as a key) from a table
* if found, return the entry pointer, otherwise return NULL
*/
static const ftm_strmap_entry_t*
ftm_get_strmap_info(int32 id, const ftm_strmap_entry_t *p_table, uint32 num_entries)
{
int i;
const ftm_strmap_entry_t *p_entry;
/* scan thru the table till end */
p_entry = p_table;
for (i = 0; i < (int) num_entries; i++)
{
if (p_entry->id == id)
return p_entry;
p_entry++; /* next entry */
}
return NULL; /* not found */
}
/*
* map enum to a text-string for display, this function is called by the following:
* For debug/trace:
* ftm_[cmdid|tlvid]_to_str()
* For TLV-output log for 'get' commands
* ftm_[method|tmu|caps|status|state]_value_to_logstr()
* Input:
* pTable -- point to a 'enum to string' table.
*/
static const char *
ftm_map_id_to_str(int32 id, const ftm_strmap_entry_t *p_table, uint32 num_entries)
{
const ftm_strmap_entry_t*p_entry = ftm_get_strmap_info(id, p_table, num_entries);
if (p_entry)
return (p_entry->text);
return "invalid";
}
#if defined(WL_CFG80211) && defined(RTT_DEBUG)
/* define entry, e.g. { WL_PROXD_CMD_xxx, "WL_PROXD_CMD_xxx" } */
#define DEF_STRMAP_ENTRY(id) { (id), #id }
/* ftm cmd-id mapping */
static const ftm_strmap_entry_t ftm_cmdid_map[] = {
/* {wl_proxd_cmd_t(WL_PROXD_CMD_xxx), "WL_PROXD_CMD_xxx" }, */
DEF_STRMAP_ENTRY(WL_PROXD_CMD_NONE),
DEF_STRMAP_ENTRY(WL_PROXD_CMD_GET_VERSION),
DEF_STRMAP_ENTRY(WL_PROXD_CMD_ENABLE),
DEF_STRMAP_ENTRY(WL_PROXD_CMD_DISABLE),
DEF_STRMAP_ENTRY(WL_PROXD_CMD_CONFIG),
DEF_STRMAP_ENTRY(WL_PROXD_CMD_START_SESSION),
DEF_STRMAP_ENTRY(WL_PROXD_CMD_BURST_REQUEST),
DEF_STRMAP_ENTRY(WL_PROXD_CMD_STOP_SESSION),
DEF_STRMAP_ENTRY(WL_PROXD_CMD_DELETE_SESSION),
DEF_STRMAP_ENTRY(WL_PROXD_CMD_GET_RESULT),
DEF_STRMAP_ENTRY(WL_PROXD_CMD_GET_INFO),
DEF_STRMAP_ENTRY(WL_PROXD_CMD_GET_STATUS),
DEF_STRMAP_ENTRY(WL_PROXD_CMD_GET_SESSIONS),
DEF_STRMAP_ENTRY(WL_PROXD_CMD_GET_COUNTERS),
DEF_STRMAP_ENTRY(WL_PROXD_CMD_CLEAR_COUNTERS),
DEF_STRMAP_ENTRY(WL_PROXD_CMD_COLLECT),
DEF_STRMAP_ENTRY(WL_PROXD_CMD_TUNE),
DEF_STRMAP_ENTRY(WL_PROXD_CMD_DUMP),
DEF_STRMAP_ENTRY(WL_PROXD_CMD_START_RANGING),
DEF_STRMAP_ENTRY(WL_PROXD_CMD_STOP_RANGING),
DEF_STRMAP_ENTRY(WL_PROXD_CMD_GET_RANGING_INFO),
};
/*
* map a ftm cmd-id to a text-string for display
*/
const char *
ftm_cmdid_to_str(uint16 cmdid)
{
return ftm_map_id_to_str((int32) cmdid, &ftm_cmdid_map[0], ARRAYSIZE(ftm_cmdid_map));
}
#endif /* WL_CFG80211 && RTT_DEBUG */
/*
* convert BCME_xxx error codes into related error strings
* note, bcmerrorstr() defined in bcmutils is for BCMDRIVER only,
* this duplicate copy is for WL access and may need to clean up later
*/
static const char *ftm_bcmerrorstrtable[] = BCMERRSTRINGTABLE;
static const char *
ftm_status_value_to_logstr(wl_proxd_status_t status)
{
static char ftm_msgbuf_status_undef[32];
const ftm_strmap_entry_t *p_loginfo;
int bcmerror;
/* check if within BCME_xxx error range */
bcmerror = (int) status;
if (VALID_BCMERROR(bcmerror))
return ftm_bcmerrorstrtable[-bcmerror];
/* otherwise, look for 'proxd ftm status' range */
p_loginfo = ftm_get_strmap_info((int32) status,
&ftm_status_value_loginfo[0], ARRAYSIZE(ftm_status_value_loginfo));
if (p_loginfo)
return p_loginfo->text;
/* report for 'out of range' FTM-status error code */
memset(ftm_msgbuf_status_undef, 0, sizeof(ftm_msgbuf_status_undef));
snprintf(ftm_msgbuf_status_undef, sizeof(ftm_msgbuf_status_undef),
"Undefined status %d", status);
return &ftm_msgbuf_status_undef[0];
}
static const char *
ftm_tmu_value_to_logstr(wl_proxd_tmu_t tmu)
{
return ftm_map_id_to_str((int32)tmu,
&ftm_tmu_value_loginfo[0], ARRAYSIZE(ftm_tmu_value_loginfo));
}
static const ftm_strmap_entry_t*
ftm_get_event_type_loginfo(wl_proxd_event_type_t event_type)
{
/* look up 'event-type' from a predefined table */
return ftm_get_strmap_info((int32) event_type,
ftm_event_type_loginfo, ARRAYSIZE(ftm_event_type_loginfo));
}
static const char *
ftm_session_state_value_to_logstr(wl_proxd_session_state_t state)
{
return ftm_map_id_to_str((int32)state, &ftm_session_state_value_loginfo[0],
ARRAYSIZE(ftm_session_state_value_loginfo));
}
#ifdef WL_CFG80211
/*
* send 'proxd' iovar for all ftm get-related commands
*/
static int
rtt_do_get_ioctl(dhd_pub_t *dhd, wl_proxd_iov_t *p_proxd_iov, uint16 proxd_iovsize,
ftm_subcmd_info_t *p_subcmd_info)
{
wl_proxd_iov_t *p_iovresp = (wl_proxd_iov_t *)resp_buf;
int status;
int tlvs_len;
/* send getbuf proxd iovar */
status = dhd_getiovar(dhd, 0, "proxd", (char *)p_proxd_iov,
proxd_iovsize, (char **)&p_iovresp, WLC_IOCTL_SMLEN);
if (status != BCME_OK) {
DHD_RTT_ERR(("%s: failed to send getbuf proxd iovar (CMD ID : %d), status=%d\n",
__FUNCTION__, p_subcmd_info->cmdid, status));
return status;
}
if (p_subcmd_info->cmdid == WL_PROXD_CMD_GET_VERSION) {
p_subcmd_info->version = ltoh16(p_iovresp->version);
DHD_RTT(("ftm version: 0x%x\n", ltoh16(p_iovresp->version)));
goto exit;
}
tlvs_len = ltoh16(p_iovresp->len) - WL_PROXD_IOV_HDR_SIZE;
if (tlvs_len < 0) {
DHD_RTT_ERR(("%s: alert, p_iovresp->len(%d) should not be smaller than %d\n",
__FUNCTION__, ltoh16(p_iovresp->len), (int) WL_PROXD_IOV_HDR_SIZE));
tlvs_len = 0;
}
if (tlvs_len > 0 && p_subcmd_info->handler) {
/* unpack TLVs and invokes the cbfn for processing */
status = bcm_unpack_xtlv_buf(p_proxd_iov, (uint8 *)p_iovresp->tlvs,
tlvs_len, BCM_XTLV_OPTION_ALIGN32, p_subcmd_info->handler);
}
exit:
return status;
}
static wl_proxd_iov_t *
rtt_alloc_getset_buf(dhd_pub_t *dhd, wl_proxd_method_t method, wl_proxd_session_id_t session_id,
wl_proxd_cmd_t cmdid, uint16 tlvs_bufsize, uint16 *p_out_bufsize)
{
uint16 proxd_iovsize;
wl_proxd_tlv_t *p_tlv;
wl_proxd_iov_t *p_proxd_iov = (wl_proxd_iov_t *) NULL;
*p_out_bufsize = 0; /* init */
/* calculate the whole buffer size, including one reserve-tlv entry in the header */
proxd_iovsize = sizeof(wl_proxd_iov_t) + tlvs_bufsize;
p_proxd_iov = (wl_proxd_iov_t *)MALLOCZ(dhd->osh, proxd_iovsize);
if (p_proxd_iov == NULL) {
DHD_RTT_ERR(("error: failed to allocate %d bytes of memory\n", proxd_iovsize));
return NULL;
}
/* setup proxd-FTM-method iovar header */
p_proxd_iov->version = htol16(WL_PROXD_API_VERSION_3);
p_proxd_iov->len = htol16(proxd_iovsize); /* caller may adjust it based on #of TLVs */
p_proxd_iov->cmd = htol16(cmdid);
p_proxd_iov->method = htol16(method);
p_proxd_iov->sid = htol16(session_id);
/* initialize the reserved/dummy-TLV in iovar header */
p_tlv = p_proxd_iov->tlvs;
p_tlv->id = htol16(WL_PROXD_TLV_ID_NONE);
p_tlv->len = htol16(0);
*p_out_bufsize = proxd_iovsize; /* for caller's reference */
return p_proxd_iov;
}
static int
dhd_rtt_common_get_handler(dhd_pub_t *dhd, ftm_subcmd_info_t *p_subcmd_info,
wl_proxd_method_t method,
wl_proxd_session_id_t session_id)
{
int status = BCME_OK;
uint16 proxd_iovsize = 0;
wl_proxd_iov_t *p_proxd_iov;
#ifdef RTT_DEBUG
DHD_RTT(("enter %s: method=%d, session_id=%d, cmdid=%d(%s)\n",
__FUNCTION__, method, session_id, p_subcmd_info->cmdid,
ftm_cmdid_to_str(p_subcmd_info->cmdid)));
#endif
/* alloc mem for ioctl headr + reserved 0 bufsize for tlvs (initialize to zero) */
p_proxd_iov = rtt_alloc_getset_buf(dhd, method, session_id, p_subcmd_info->cmdid,
0, &proxd_iovsize);
if (p_proxd_iov == NULL)
return BCME_NOMEM;
status = rtt_do_get_ioctl(dhd, p_proxd_iov, proxd_iovsize, p_subcmd_info);
if (status != BCME_OK) {
DHD_RTT(("%s failed: status=%d\n", __FUNCTION__, status));
}
MFREE(dhd->osh, p_proxd_iov, proxd_iovsize);
return status;
}
/*
* common handler for set-related proxd method commands which require no TLV as input
* wl proxd ftm [session-id] <set-subcmd>
* e.g.
* wl proxd ftm enable -- to enable ftm
* wl proxd ftm disable -- to disable ftm
* wl proxd ftm <session-id> start -- to start a specified session
* wl proxd ftm <session-id> stop -- to cancel a specified session;
* state is maintained till session is delete.
* wl proxd ftm <session-id> delete -- to delete a specified session
* wl proxd ftm [<session-id>] clear-counters -- to clear counters
* wl proxd ftm <session-id> burst-request -- on initiator: to send burst request;
* on target: send FTM frame
* wl proxd ftm <session-id> collect
* wl proxd ftm tune (TBD)
*/
static int
dhd_rtt_common_set_handler(dhd_pub_t *dhd, const ftm_subcmd_info_t *p_subcmd_info,
wl_proxd_method_t method, wl_proxd_session_id_t session_id)
{
uint16 proxd_iovsize;
wl_proxd_iov_t *p_proxd_iov;
int ret;
#ifdef RTT_DEBUG
DHD_RTT(("enter %s: method=%d, session_id=%d, cmdid=%d(%s)\n",
__FUNCTION__, method, session_id, p_subcmd_info->cmdid,
ftm_cmdid_to_str(p_subcmd_info->cmdid)));
#endif
/* allocate and initialize a temp buffer for 'set proxd' iovar */
proxd_iovsize = 0;
p_proxd_iov = rtt_alloc_getset_buf(dhd, method, session_id, p_subcmd_info->cmdid,
0, &proxd_iovsize); /* no TLV */
if (p_proxd_iov == NULL)
return BCME_NOMEM;
/* no TLV to pack, simply issue a set-proxd iovar */
ret = dhd_iovar(dhd, 0, "proxd", (char *)p_proxd_iov, proxd_iovsize, NULL, 0, TRUE);
#ifdef RTT_DEBUG
if (ret != BCME_OK) {
DHD_RTT(("error: IOVAR failed, status=%d\n", ret));
}
#endif
/* clean up */
MFREE(dhd->osh, p_proxd_iov, proxd_iovsize);
return ret;
}
#endif /* WL_CFG80211 */
/* gets the length and returns the version
* of the wl_proxd_collect_event_t version
*/
static uint
rtt_collect_data_event_ver(uint16 len)
{
if (len > sizeof(wl_proxd_collect_event_data_v3_t)) {
return WL_PROXD_COLLECT_EVENT_DATA_VERSION_MAX;
} else if (len == sizeof(wl_proxd_collect_event_data_v4_t)) {
return WL_PROXD_COLLECT_EVENT_DATA_VERSION_4;
} else if (len == sizeof(wl_proxd_collect_event_data_v3_t)) {
return WL_PROXD_COLLECT_EVENT_DATA_VERSION_3;
} else if (len == sizeof(wl_proxd_collect_event_data_v2_t)) {
return WL_PROXD_COLLECT_EVENT_DATA_VERSION_2;
} else {
return WL_PROXD_COLLECT_EVENT_DATA_VERSION_1;
}
}
static int
rtt_collect_event_data_display(uint8 ver, bcm_xtlv_t *tlv, const uint8 *p_data, uint16 len)
{
int i;
int ret = BCME_OK;
wl_proxd_collect_event_data_v1_t *p_collect_data_v1 = NULL;
wl_proxd_collect_event_data_v2_t *p_collect_data_v2 = NULL;
wl_proxd_collect_event_data_v3_t *p_collect_data_v3 = NULL;
wl_proxd_collect_event_data_v4_t *p_collect_data_v4 = NULL;
if (!tlv || !p_data) {
return BCME_ERROR;
}
if (!(len < BCM_XTLV_MAX_DATA_SIZE_EX(BCM_XTLV_OPTION_NONE))) {
return BCME_BUFTOOLONG;
}
switch (ver) {
case WL_PROXD_COLLECT_EVENT_DATA_VERSION_1:
DHD_RTT(("\tVERSION_1\n"));
ret = memcpy_s(tlv->data, tlv->len, p_data,
sizeof(wl_proxd_collect_event_data_v1_t));
if (ret != BCME_OK) {
break;
}
p_collect_data_v1 = (wl_proxd_collect_event_data_v1_t *)tlv->data;
DHD_RTT(("\tH_RX\n"));
for (i = 0; i < K_TOF_COLLECT_H_SIZE_20MHZ; i++) {
p_collect_data_v1->H_RX[i] = ltoh32_ua(&p_collect_data_v1->H_RX[i]);
DHD_RTT(("\t%u\n", p_collect_data_v1->H_RX[i]));
}
DHD_RTT(("\n"));
DHD_RTT(("\tH_LB\n"));
for (i = 0; i < K_TOF_COLLECT_H_SIZE_20MHZ; i++) {
p_collect_data_v1->H_LB[i] = ltoh32_ua(&p_collect_data_v1->H_LB[i]);
DHD_RTT(("\t%u\n", p_collect_data_v1->H_LB[i]));
}
DHD_RTT(("\n"));
DHD_RTT(("\tri_rr\n"));
for (i = 0; i < FTM_TPK_RI_RR_LEN; i++) {
DHD_RTT(("\t%u\n", p_collect_data_v1->ri_rr[i]));
}
p_collect_data_v1->phy_err_mask = ltoh32_ua(&p_collect_data_v1->phy_err_mask);
DHD_RTT(("\tphy_err_mask=0x%x\n", p_collect_data_v1->phy_err_mask));
break;
case WL_PROXD_COLLECT_EVENT_DATA_VERSION_2:
ret = memcpy_s(tlv->data, tlv->len, p_data,
sizeof(wl_proxd_collect_event_data_v2_t));
if (ret != BCME_OK) {
break;
}
p_collect_data_v2 = (wl_proxd_collect_event_data_v2_t *)tlv->data;
DHD_RTT(("\tH_RX\n"));
for (i = 0; i < K_TOF_COLLECT_H_SIZE_20MHZ; i++) {
p_collect_data_v2->H_RX[i] = ltoh32_ua(&p_collect_data_v2->H_RX[i]);
DHD_RTT(("\t%u\n", p_collect_data_v2->H_RX[i]));
}
DHD_RTT(("\n"));
DHD_RTT(("\tH_LB\n"));
for (i = 0; i < K_TOF_COLLECT_H_SIZE_20MHZ; i++) {
p_collect_data_v2->H_LB[i] = ltoh32_ua(&p_collect_data_v2->H_LB[i]);
DHD_RTT(("\t%u\n", p_collect_data_v2->H_LB[i]));
}
DHD_RTT(("\n"));
DHD_RTT(("\tri_rr\n"));
for (i = 0; i < FTM_TPK_RI_RR_LEN_SECURE_2_0; i++) {
DHD_RTT(("\t%u\n", p_collect_data_v2->ri_rr[i]));
}
p_collect_data_v2->phy_err_mask = ltoh32_ua(&p_collect_data_v2->phy_err_mask);
DHD_RTT(("\tphy_err_mask=0x%x\n", p_collect_data_v2->phy_err_mask));
break;
case WL_PROXD_COLLECT_EVENT_DATA_VERSION_3:
ret = memcpy_s(tlv->data, tlv->len, p_data,
sizeof(wl_proxd_collect_event_data_v3_t));
if (ret != BCME_OK) {
break;
}
p_collect_data_v3 = (wl_proxd_collect_event_data_v3_t *)tlv->data;
switch (p_collect_data_v3->version) {
case WL_PROXD_COLLECT_EVENT_DATA_VERSION_3:
if (p_collect_data_v3->length !=
(len - OFFSETOF(wl_proxd_collect_event_data_v3_t, H_LB))) {
DHD_RTT(("\tversion/length mismatch\n"));
break;
}
DHD_RTT(("\tH_RX\n"));
for (i = 0; i < K_TOF_COLLECT_H_SIZE_20MHZ; i++) {
p_collect_data_v3->H_RX[i] =
ltoh32_ua(&p_collect_data_v3->H_RX[i]);
DHD_RTT(("\t%u\n", p_collect_data_v3->H_RX[i]));
}
DHD_RTT(("\n"));
DHD_RTT(("\tH_LB\n"));
for (i = 0; i < K_TOF_COLLECT_H_SIZE_20MHZ; i++) {
p_collect_data_v3->H_LB[i] =
ltoh32_ua(&p_collect_data_v3->H_LB[i]);
DHD_RTT(("\t%u\n", p_collect_data_v3->H_LB[i]));
}
DHD_RTT(("\n"));
DHD_RTT(("\tri_rr\n"));
for (i = 0; i < FTM_TPK_RI_RR_LEN_SECURE_2_0; i++) {
DHD_RTT(("\t%u\n", p_collect_data_v3->ri_rr[i]));
}
p_collect_data_v3->phy_err_mask =
ltoh32_ua(&p_collect_data_v3->phy_err_mask);
DHD_RTT(("\tphy_err_mask=0x%x\n", p_collect_data_v3->phy_err_mask));
break;
/* future case */
}
break;
case WL_PROXD_COLLECT_EVENT_DATA_VERSION_4:
ret = memcpy_s(tlv->data, tlv->len, p_data,
sizeof(wl_proxd_collect_event_data_v4_t));
if (ret != BCME_OK) {
break;
}
p_collect_data_v4 = (wl_proxd_collect_event_data_v4_t *)tlv->data;
switch (p_collect_data_v4->version) {
case WL_PROXD_COLLECT_EVENT_DATA_VERSION_4:
if (p_collect_data_v4->length !=
(len - OFFSETOF(wl_proxd_collect_event_data_v4_t, H_LB))) {
DHD_RTT(("\tversion/length mismatch\n"));
break;
}
DHD_RTT(("\tH_RX\n"));
for (i = 0; i < K_TOF_COLLECT_H_SIZE_20MHZ; i++) {
p_collect_data_v4->H_RX[i] =
ltoh32_ua(&p_collect_data_v4->H_RX[i]);
DHD_RTT(("\t%u\n", p_collect_data_v4->H_RX[i]));
}
DHD_RTT(("\n"));
DHD_RTT(("\tH_LB\n"));
for (i = 0; i < K_TOF_COLLECT_H_SIZE_20MHZ; i++) {
p_collect_data_v4->H_LB[i] =
ltoh32_ua(&p_collect_data_v4->H_LB[i]);
DHD_RTT(("\t%u\n", p_collect_data_v4->H_LB[i]));
}
DHD_RTT(("\n"));
DHD_RTT(("\tri_rr\n"));
for (i = 0; i < FTM_TPK_RI_RR_LEN_SECURE_2_0_5G; i++) {
DHD_RTT(("\t%u\n", p_collect_data_v4->ri_rr[i]));
}
p_collect_data_v4->phy_err_mask =
ltoh32_ua(&p_collect_data_v4->phy_err_mask);
DHD_RTT(("\tphy_err_mask=0x%x\n", p_collect_data_v4->phy_err_mask));
break;
/* future case */
}