blob: bcf7e407c9cd02ed8905753a9f1437c2740f1025 [file] [log] [blame]
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001/*
2 * Sigma Control API DUT (NAN functionality)
3 * Copyright (c) 2014-2015, Qualcomm Atheros, Inc.
4 * All Rights Reserved.
5 * Licensed under the Clear BSD license. See README for more details.
6 */
7
8#include "sigma_dut.h"
9#include <sys/stat.h>
10#include "wpa_ctrl.h"
11#include "wpa_helpers.h"
12#include "wifi_hal.h"
13#include "nan.h"
14
15pthread_cond_t gCondition;
16pthread_mutex_t gMutex;
17
18wifi_handle global_handle;
19static int nan_state = 0;
20static int event_anyresponse = 0;
21static int is_fam = 0;
22
23uint16_t global_header_handle = 0;
24uint32_t global_match_handle = 0;
25
26#define MAC_ADDR_ARRAY(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
27#define MAC_ADDR_STR "%02x:%02x:%02x:%02x:%02x:%02x"
28#ifndef ETH_ALEN
29#define ETH_ALEN 6
30#endif
31
32struct sigma_dut *global_dut = NULL;
33static char global_nan_mac_addr[ETH_ALEN];
34static char global_event_resp_buf[1024];
35
36static int nan_further_availability_tx(struct sigma_dut *dut,
37 struct sigma_conn *conn,
38 struct sigma_cmd *cmd);
39static int nan_further_availability_rx(struct sigma_dut *dut,
40 struct sigma_conn *conn,
41 struct sigma_cmd *cmd);
42
43
44void nan_hex_dump(struct sigma_dut *dut, uint8_t *data, size_t len)
45{
46 char buf[512];
47 uint16_t index;
48 uint8_t *ptr;
49 int pos;
50
51 memset(buf, 0, sizeof(buf));
52 ptr = data;
53 pos = 0;
54 for (index = 0; index < len; index++) {
55 pos += sprintf(&(buf[pos]), "%02x ", *ptr++);
56 if (pos > 508)
57 break;
58 }
59 sigma_dut_print(dut, DUT_MSG_INFO, "HEXDUMP len=[%d]", (int) len);
60 sigma_dut_print(dut, DUT_MSG_INFO, "buf:%s", buf);
61}
62
63
64int nan_parse_hex(unsigned char c)
65{
66 if (c >= '0' && c <= '9')
67 return c - '0';
68 if (c >= 'a' && c <= 'f')
69 return c - 'a' + 10;
70 if (c >= 'A' && c <= 'F')
71 return c - 'A' + 10;
72 return 0;
73}
74
75
76int nan_parse_token(const char *tokenIn, u8 *tokenOut, int *filterLen)
77{
78 int total_len = 0, len = 0;
79 char *saveptr = NULL;
80
81 tokenIn = strtok_r((char *) tokenIn, ":", &saveptr);
82 while (tokenIn != NULL) {
83 len = strlen(tokenIn);
84 if (len == 1 && *tokenIn == '*')
85 len = 0;
86 tokenOut[total_len++] = (u8) len;
87 if (len != 0)
88 memcpy((u8 *) tokenOut + total_len, tokenIn, len);
89 total_len += len;
90 tokenIn = strtok_r(NULL, ":", &saveptr);
91 }
92 *filterLen = total_len;
93 return 0;
94}
95
96
97int nan_parse_mac_address(struct sigma_dut *dut, const char *arg, u8 *addr)
98{
99 if (strlen(arg) != 17) {
100 sigma_dut_print(dut, DUT_MSG_ERROR, "Invalid mac address %s",
101 arg);
102 sigma_dut_print(dut, DUT_MSG_ERROR,
103 "expected format xx:xx:xx:xx:xx:xx");
104 return -1;
105 }
106
107 addr[0] = nan_parse_hex(arg[0]) << 4 | nan_parse_hex(arg[1]);
108 addr[1] = nan_parse_hex(arg[3]) << 4 | nan_parse_hex(arg[4]);
109 addr[2] = nan_parse_hex(arg[6]) << 4 | nan_parse_hex(arg[7]);
110 addr[3] = nan_parse_hex(arg[9]) << 4 | nan_parse_hex(arg[10]);
111 addr[4] = nan_parse_hex(arg[12]) << 4 | nan_parse_hex(arg[13]);
112 addr[5] = nan_parse_hex(arg[15]) << 4 | nan_parse_hex(arg[16]);
113
114 return 0;
115}
116
117
118int nan_parse_mac_address_list(struct sigma_dut *dut, const char *input,
119 u8 *output, u16 max_addr_allowed)
120{
121 /*
122 * Reads a list of mac address separated by space. Each MAC address
123 * should have the format of aa:bb:cc:dd:ee:ff.
124 */
125 char *saveptr;
126 char *token;
127 int i = 0;
128
129 for (i = 0; i < max_addr_allowed; i++) {
130 token = strtok_r((i == 0) ? (char *) input : NULL,
131 " ", &saveptr);
132 if (token) {
133 nan_parse_mac_address(dut, token, output);
134 output += NAN_MAC_ADDR_LEN;
135 } else
136 break;
137 }
138
139 sigma_dut_print(dut, DUT_MSG_INFO, "Num MacAddress:%d", i);
140
141 return i;
142}
143
144
145int nan_parse_hex_string(struct sigma_dut *dut, const char *input,
146 u8 *output, int *outputlen)
147{
148 int i = 0;
149 int j = 0;
150
151 for (i = 0; i < (int) strlen(input) && j < *outputlen; i += 2) {
152 output[j] = nan_parse_hex(input[i]);
153 if (i + 1 < (int) strlen(input)) {
154 output[j] = ((output[j] << 4) |
155 nan_parse_hex(input[i + 1]));
156 }
157 j++;
158 }
159 *outputlen = j;
160 sigma_dut_print(dut, DUT_MSG_INFO, "Input:%s inputlen:%d outputlen:%d",
161 input, (int) strlen(input), (int) *outputlen);
162 return 0;
163}
164
165
166int wait(struct timespec abstime)
167{
168 struct timeval now;
169
170 gettimeofday(&now, NULL);
171
172 abstime.tv_sec += now.tv_sec;
173 if (((abstime.tv_nsec + now.tv_usec * 1000) > 1000 * 1000 * 1000) ||
174 (abstime.tv_nsec + now.tv_usec * 1000 < 0)) {
175 abstime.tv_sec += 1;
176 abstime.tv_nsec += now.tv_usec * 1000;
177 abstime.tv_nsec -= 1000 * 1000 * 1000;
178 } else {
179 abstime.tv_nsec += now.tv_usec * 1000;
180 }
181
182 return pthread_cond_timedwait(&gCondition, &gMutex, &abstime);
183}
184
185
186int nan_cmd_sta_preset_testparameters(struct sigma_dut *dut,
187 struct sigma_conn *conn,
188 struct sigma_cmd *cmd)
189{
190 const char *oper_chan = get_param(cmd, "oper_chan");
191 int channel = 0;
192
193 channel = atoi(oper_chan);
194 dut->sta_channel = channel;
195
196 return 0;
197}
198
199
200int sigma_nan_enable(struct sigma_dut *dut, struct sigma_conn *conn,
201 struct sigma_cmd *cmd)
202{
203 const char *master_pref = get_param(cmd, "MasterPref");
204 const char *rand_fac = get_param(cmd, "RandFactor");
205 const char *hop_count = get_param(cmd, "HopCount");
206 const char *high_tsf = get_param(cmd, "HighTSF");
207 const char *sdftx_band = get_param(cmd, "SDFTxBand");
208 const char *oper_chan = get_param(cmd, "oper_chn");
209 const char *further_avail_ind = get_param(cmd, "FurtherAvailInd");
210 const char *band = get_param(cmd, "Band");
211 const char *only_5g = get_param(cmd, "5GOnly");
212 struct timespec abstime;
213 NanEnableRequest req;
214
215 memset(&req, 0, sizeof(NanEnableRequest));
216 req.header.handle = 0xFFFF;
217 req.header.transaction_id = 0;
218 req.support_5g = 1;
219 req.config_5g_beacons = 1;
220 req.beacon_5g_val = 1;
221 req.config_5g_discovery = 1;
222 req.discovery_5g_val = 1;
223 req.cluster_low = 0;
224 req.cluster_high = 0xFFFF;
225 req.sid_beacon = 1;
226 req.rssi_close = 60;
227 req.rssi_middle = 70;
228 req.rssi_proximity = 70;
229 req.hop_count_limit = 2;
230 req.random_time = 120;
231 req.master_pref = 30;
232 req.periodic_scan_interval = 20;
233
234 /* This is a debug hack to becon in channel 11 */
235 if (oper_chan) {
236 req.config_2dot4g_support = 1;
237 req.support_2dot4g_val = 111;
238 }
239
240 if (dut->device_type == STA_testbed) {
241 sigma_dut_print(dut, DUT_MSG_INFO, "Device in Test Bed mode");
242 req.config_debug_flags = 1;
243 req.debug_flags_val = 0x80000000;
244 if (high_tsf) {
245 if (strcasecmp(high_tsf, "On") == 0)
246 req.debug_flags_val = 0xc0000000;
247 }
248 }
249
250 if (master_pref) {
251 int master_pref_val = strtoul(master_pref, NULL, 0);
252
253 req.master_pref = master_pref_val;
254 }
255
256 if (rand_fac) {
257 int rand_fac_val = strtoul(rand_fac, NULL, 0);
258
259 req.config_random_factor_force = 1;
260 req.random_factor_force_val = rand_fac_val;
261 }
262
263 if (hop_count) {
264 int hop_count_val = strtoul(hop_count, NULL, 0);
265
266 req.config_hop_count_force = 1;
267 req.hop_count_force_val = hop_count_val;
268 }
269
270 if (sdftx_band) {
271 if (strcasecmp(sdftx_band, "5G") == 0) {
272 req.config_2dot4g_support = 1;
273 req.support_2dot4g_val = 0;
274 }
275 }
276
277 if (band) {
278 if (strcasecmp(band, "24G") == 0) {
279 sigma_dut_print(dut, DUT_MSG_INFO,
280 "Band 2.4GHz selected");
281 /* Enable 2.4G support */
282 req.config_2dot4g_support = 1;
283 req.support_2dot4g_val = 1;
284 req.config_2dot4g_beacons = 1;
285 req.beacon_2dot4g_val = 1;
286 req.config_2dot4g_discovery = 1;
287 req.discovery_2dot4g_val = 1;
288
289 /* Disable 5G support */
290 req.support_5g = 0;
291 req.config_5g_beacons = 1;
292 req.beacon_5g_val = 0;
293 req.config_5g_discovery = 1;
294 req.discovery_5g_val = 0;
295 }
296 }
297
298 if (further_avail_ind) {
299 sigma_dut_print(dut, DUT_MSG_INFO, "FAM Test Enabled");
300 if (strcasecmp(further_avail_ind, "tx") == 0) {
301 is_fam = 1;
302 nan_further_availability_tx(dut, conn, cmd);
303 return 0;
304 } else if (strcasecmp(further_avail_ind, "rx") == 0) {
305 nan_further_availability_rx(dut, conn, cmd);
306 return 0;
307 }
308 }
309
310 if (only_5g && atoi(only_5g)) {
311 sigma_dut_print(dut, DUT_MSG_INFO, "5GHz only enabled");
312 req.config_2dot4g_support = 1;
313 req.support_2dot4g_val = 1;
314 req.config_2dot4g_beacons = 1;
315 req.beacon_2dot4g_val = 0;
316 req.config_2dot4g_discovery = 1;
317 req.discovery_2dot4g_val = 1;
318 }
319
320 nan_enable_request(0, global_handle, &req);
321 abstime.tv_sec = 4;
322 abstime.tv_nsec = 0;
323 return wait(abstime);
324}
325
326
327int sigma_nan_disable(struct sigma_dut *dut, struct sigma_conn *conn,
328 struct sigma_cmd *cmd)
329{
330 NanDisableRequest req;
331 struct timespec abstime;
332
333 memset(&req, 0, sizeof(NanDisableRequest));
334 req.header.handle = 0x0;
335 req.header.transaction_id = 0;
336
337 nan_disable_request(0, global_handle, &req);
338
339 abstime.tv_sec = 4;
340 abstime.tv_nsec = 0;
341 return wait(abstime);
342}
343
344
345int sigma_nan_config_enable(struct sigma_dut *dut, struct sigma_conn *conn,
346 struct sigma_cmd *cmd)
347{
348 const char *master_pref = get_param(cmd, "MasterPref");
349 const char *rand_fac = get_param(cmd, "RandFactor");
350 const char *hop_count = get_param(cmd, "HopCount");
351 struct timespec abstime;
352 NanConfigRequest req;
353
354 memset(&req, 0, sizeof(NanConfigRequest));
355 req.header.handle = 0x0;
356 req.header.transaction_id = 0;
357 req.config_rssi_proximity = 1;
358 req.rssi_proximity = 70;
359
360 if (master_pref) {
361 int master_pref_val = strtoul(master_pref, NULL, 0);
362
363 req.config_master_pref = 1;
364 req.master_pref = master_pref_val;
365 }
366
367 if (rand_fac) {
368 int rand_fac_val = strtoul(rand_fac, NULL, 0);
369
370 req.config_random_factor_force = 1;
371 req.random_factor_force_val = rand_fac_val;
372 }
373
374 if (hop_count) {
375 int hop_count_val = strtoul(hop_count, NULL, 0);
376
377 req.config_hop_count_force = 1;
378 req.hop_count_force_val = hop_count_val;
379 }
380
381 nan_config_request(0, global_handle, &req);
382
383 abstime.tv_sec = 4;
384 abstime.tv_nsec = 0;
385
386 return wait(abstime);
387}
388
389
390static int sigma_nan_subscribe_request(struct sigma_dut *dut,
391 struct sigma_conn *conn,
392 struct sigma_cmd *cmd)
393{
394 const char *subscribe_type = get_param(cmd, "SubscribeType");
395 const char *service_name = get_param(cmd, "ServiceName");
396 const char *disc_range = get_param(cmd, "DiscoveryRange");
397 const char *rx_match_filter = get_param(cmd, "rxMatchFilter");
398 const char *tx_match_filter = get_param(cmd, "txMatchFilter");
399 const char *sdftx_dw = get_param(cmd, "SDFTxDW");
400 const char *discrange_ltd = get_param(cmd, "DiscRangeLtd");
401 const char *include_bit = get_param(cmd, "IncludeBit");
402 const char *mac = get_param(cmd, "MAC");
403 const char *srf_type = get_param(cmd, "SRFType");
404 NanSubscribeRequest req;
405 int filter_len_rx = 0, filter_len_tx = 0;
406 u8 input_rx[NAN_MAX_MATCH_FILTER_LEN];
407 u8 input_tx[NAN_MAX_MATCH_FILTER_LEN];
408
409 memset(&req, 0, sizeof(NanSubscribeRequest));
410 req.header.handle = 0xFFFF;
411 req.header.transaction_id = 0;
412 req.ttl = 0;
413 req.period = 1000;
414 req.subscribe_type = 1;
415 req.serviceResponseFilter = 1; /* MAC */
416 req.serviceResponseInclude = 0;
417 req.ssiRequiredForMatchIndication = 0;
418 req.subscribe_match = NAN_MATCH_ALG_MATCH_CONTINUOUS;
419 req.subscribe_count = 0;
420
421 if (subscribe_type) {
422 if (strcasecmp(subscribe_type, "Active") == 0) {
423 req.subscribe_type = 1;
424 } else if (strcasecmp(subscribe_type, "Passive") == 0) {
425 req.subscribe_type = 0;
426 } else if (strcasecmp(subscribe_type, "Cancel") == 0) {
427 NanSubscribeCancelRequest req;
428
429 memset(&req, 0, sizeof(NanSubscribeCancelRequest));
430 req.header.handle = 128;
431 req.header.transaction_id = 0;
432 nan_subscribe_cancel_request(0, global_handle, &req);
433 return 0;
434 }
435 }
436
437 if (disc_range)
438 req.rssi_threshold_flag = atoi(disc_range);
439
440 if (sdftx_dw)
441 req.subscribe_count = atoi(sdftx_dw);
442
443 /* Check this once again if config can be called here (TBD) */
444 if (discrange_ltd)
445 req.rssi_threshold_flag = atoi(discrange_ltd);
446
447 if (include_bit) {
448 int include_bit_val = atoi(include_bit);
449
450 req.serviceResponseInclude = include_bit_val;
451 sigma_dut_print(dut, DUT_MSG_INFO, "Includebit set %d",
452 req.serviceResponseInclude);
453 }
454
455 if (srf_type) {
456 int srf_type_val = atoi(srf_type);
457
458 if (srf_type_val == 1)
459 req.serviceResponseFilter = 0; /* Bloom */
460 else
461 req.serviceResponseFilter = 1; /* MAC */
462 req.useServiceResponseFilter = 1;
463 sigma_dut_print(dut, DUT_MSG_INFO, "srfFilter %d",
464 req.serviceResponseFilter);
465 }
466
467 if (mac) {
468 sigma_dut_print(dut, DUT_MSG_INFO, "MAC_ADDR List %s", mac);
469 req.num_intf_addr_present = nan_parse_mac_address_list(
470 dut, mac, &req.intf_addr[0][0],
471 NAN_MAX_SUBSCRIBE_MAX_ADDRESS);
472 }
473
474 memset(input_rx, 0, sizeof(input_rx));
475 memset(input_tx, 0, sizeof(input_tx));
476 if (rx_match_filter) {
477 nan_parse_token(rx_match_filter, input_rx, &filter_len_rx);
478 sigma_dut_print(dut, DUT_MSG_INFO, "RxFilterLen %d",
479 filter_len_rx);
480 }
481 if (tx_match_filter) {
482 nan_parse_token(tx_match_filter, input_tx, &filter_len_tx);
483 sigma_dut_print(dut, DUT_MSG_INFO, "TxFilterLen %d",
484 filter_len_tx);
485 }
486
487 if (tx_match_filter) {
488 req.tx_match_filter_len = filter_len_tx;
489 memcpy(req.tx_match_filter, input_tx, filter_len_tx);
490 nan_hex_dump(dut, req.tx_match_filter, filter_len_tx);
491 }
492 if (rx_match_filter) {
493 req.rx_match_filter_len = filter_len_rx;
494 memcpy(req.rx_match_filter, input_rx, filter_len_rx);
495 nan_hex_dump(dut, req.rx_match_filter, filter_len_rx);
496 }
497
498 strlcpy((char *) req.service_name, service_name,
499 strlen(service_name) + 1);
500 req.service_name_len = strlen(service_name);
501
502 nan_subscribe_request(0, global_handle, &req);
503 return 0;
504}
505
506
507int config_post_disc_attr(void)
508{
509 NanConfigRequest configReq;
510
511 memset(&configReq, 0, sizeof(NanConfigRequest));
512 configReq.header.handle = 0x0;
513 configReq.header.transaction_id = 0;
514
515 /* Configure Post disc attr */
516 /* Make these defines and use correct enum */
517 configReq.config_discovery_attr = 1;
518 configReq.discovery_attr_val.type = 4; /* Further Nan discovery */
519 configReq.discovery_attr_val.role = 0;
520 configReq.discovery_attr_val.transmit_freq = 1;
521 configReq.discovery_attr_val.duration = 0;
522 configReq.discovery_attr_val.avail_interval_bitmap = 0x00000008;
523
524 nan_config_request(0, global_handle, &configReq);
525 return 0;
526}
527
528
529int sigma_nan_publish_request(struct sigma_dut *dut, struct sigma_conn *conn,
530 struct sigma_cmd *cmd)
531{
532 const char *publish_type = get_param(cmd, "PublishType");
533 const char *service_name = get_param(cmd, "ServiceName");
534 const char *disc_range = get_param(cmd, "DiscoveryRange");
535 const char *rx_match_filter = get_param(cmd, "rxMatchFilter");
536 const char *tx_match_filter = get_param(cmd, "txMatchFilter");
537 const char *sdftx_dw = get_param(cmd, "SDFTxDW");
538 const char *discrange_ltd = get_param(cmd, "DiscRangeLtd");
539 NanPublishRequest req;
540 int filter_len_rx = 0, filter_len_tx = 0;
541 u8 input_rx[NAN_MAX_MATCH_FILTER_LEN];
542 u8 input_tx[NAN_MAX_MATCH_FILTER_LEN];
543
544 memset(&req, 0, sizeof(NanPublishRequest));
545 req.header.handle = 0xFFFF;
546 req.header.transaction_id = 0;
547 req.ttl = 0;
548 req.period = 500;
549 req.replied_event_flag = 1;
550 req.publish_type = NAN_PUBLISH_TYPE_UNSOLICITED;
551 req.tx_type = NAN_TX_TYPE_BROADCAST;
552 req.publish_count = 0;
553 strlcpy((char *) req.service_name, service_name,
554 strlen(service_name) + 1);
555 req.service_name_len = strlen(service_name);
556
557 if (publish_type) {
558 if (strcasecmp(publish_type, "Solicited") == 0) {
559 req.publish_type = NAN_PUBLISH_TYPE_SOLICITED;
560 } else if (strcasecmp(publish_type, "Cancel") == 0) {
561 NanPublishCancelRequest req;
562
563 memset(&req, 0, sizeof(NanPublishCancelRequest));
564 req.header.handle = 1;
565 req.header.transaction_id = 0;
566 nan_publish_cancel_request(0, global_handle, &req);
567 return 0;
568 }
569 }
570
571 if (disc_range)
572 req.rssi_threshold_flag = atoi(disc_range);
573
574 if (sdftx_dw)
575 req.publish_count = atoi(sdftx_dw);
576
577 if (discrange_ltd)
578 req.rssi_threshold_flag = atoi(discrange_ltd);
579
580 memset(input_rx, 0, sizeof(input_rx));
581 memset(input_tx, 0, sizeof(input_tx));
582 if (rx_match_filter) {
583 nan_parse_token(rx_match_filter, input_rx, &filter_len_rx);
584 sigma_dut_print(dut, DUT_MSG_INFO, "RxFilterLen %d",
585 filter_len_rx);
586 }
587 if (tx_match_filter) {
588 nan_parse_token(tx_match_filter, input_tx, &filter_len_tx);
589 sigma_dut_print(dut, DUT_MSG_INFO, "TxFilterLen %d",
590 filter_len_tx);
591 }
592
593 if (is_fam == 1) {
594 config_post_disc_attr();
595 /* TODO: Add comments regarding this step */
596 req.connmap = 0x10;
597 }
598
599 if (tx_match_filter) {
600 req.tx_match_filter_len = filter_len_tx;
601 memcpy(req.tx_match_filter, input_tx, filter_len_tx);
602 nan_hex_dump(dut, req.tx_match_filter, filter_len_tx);
603 }
604
605 if (rx_match_filter) {
606 req.rx_match_filter_len = filter_len_rx;
607 memcpy(req.rx_match_filter, input_rx, filter_len_rx);
608 nan_hex_dump(dut, req.rx_match_filter, filter_len_rx);
609 }
610 strlcpy((char *) req.service_name, service_name,
611 strlen(service_name) + 1);
612 req.service_name_len = strlen(service_name);
613
614 nan_publish_request(0, global_handle, &req);
615
616 return 0;
617}
618
619
620static int nan_further_availability_rx(struct sigma_dut *dut,
621 struct sigma_conn *conn,
622 struct sigma_cmd *cmd)
623{
624 const char *master_pref = get_param(cmd, "MasterPref");
625 const char *rand_fac = get_param(cmd, "RandFactor");
626 const char *hop_count = get_param(cmd, "HopCount");
627 struct timespec abstime;
628
629 NanEnableRequest req;
630
631 memset(&req, 0, sizeof(NanEnableRequest));
632 req.header.handle = 0xFFFF;
633 req.header.transaction_id = 0;
634 req.support_5g = 1;
635 req.config_5g_beacons = 1;
636 req.beacon_5g_val = 1;
637 req.config_5g_discovery = 1;
638 req.discovery_5g_val = 1;
639 req.cluster_low = 0;
640 req.cluster_high = 0xFFFF;
641 req.sid_beacon = 1;
642 req.rssi_close = 60;
643 req.rssi_middle = 70;
644 req.rssi_proximity = 70;
645 req.hop_count_limit = 2;
646 req.random_time = 120;
647 req.master_pref = 30;
648 req.periodic_scan_interval = 20;
649
650 if (dut->device_type == STA_testbed) {
651 sigma_dut_print(dut, DUT_MSG_INFO, "Device in Test Bed mode");
652 req.config_debug_flags = 1;
653 /* TODO: Make a comment here.. */
654 req.debug_flags_val = 0xA0000000;
655 }
656
657 if (master_pref)
658 req.master_pref = strtoul(master_pref, NULL, 0);
659
660 if (rand_fac) {
661 int rand_fac_val = strtoul(rand_fac, NULL, 0);
662
663 req.config_random_factor_force = 1;
664 req.random_factor_force_val = rand_fac_val;
665 }
666
667 if (hop_count) {
668 int hop_count_val = strtoul(hop_count, NULL, 0);
669
670 req.config_hop_count_force = 1;
671 req.hop_count_force_val = hop_count_val;
672 }
673
674 nan_enable_request(0, global_handle, &req);
675 abstime.tv_sec = 4;
676 abstime.tv_nsec = 0;
677
678 wait(abstime);
679 return 0;
680}
681
682
683static int nan_further_availability_tx(struct sigma_dut *dut,
684 struct sigma_conn *conn,
685 struct sigma_cmd *cmd)
686{
687 const char *master_pref = get_param(cmd, "MasterPref");
688 const char *rand_fac = get_param(cmd, "RandFactor");
689 const char *hop_count = get_param(cmd, "HopCount");
690 NanEnableRequest req;
691 NanConfigRequest configReq;
692
693 memset(&req, 0, sizeof(NanEnableRequest));
694 req.header.handle = 0xFFFF;
695 req.header.transaction_id = 0;
696 req.support_5g = 1;
697 req.config_5g_beacons = 1;
698 req.beacon_5g_val = 1;
699 req.config_5g_discovery = 1;
700 req.discovery_5g_val = 1;
701 req.cluster_low = 0;
702 req.cluster_high = 0xFFFF;
703 req.sid_beacon = 1;
704 req.rssi_close = 60;
705 req.rssi_middle = 70;
706 req.rssi_proximity = 70;
707 req.hop_count_limit = 2;
708 req.random_time = 120;
709 req.master_pref = 30;
710 req.periodic_scan_interval = 20;
711
712 if (dut->device_type == STA_testbed) {
713 sigma_dut_print(dut, DUT_MSG_INFO, "Device in Test Bed mode");
714 req.config_debug_flags = 1;
715 req.debug_flags_val = 0x00000000;
716 }
717
718 if (master_pref)
719 req.master_pref = strtoul(master_pref, NULL, 0);
720
721 if (rand_fac) {
722 int rand_fac_val = strtoul(rand_fac, NULL, 0);
723
724 req.config_random_factor_force = 1;
725 req.random_factor_force_val = rand_fac_val;
726 }
727
728 if (hop_count) {
729 int hop_count_val = strtoul(hop_count, NULL, 0);
730
731 req.config_hop_count_force = 1;
732 req.hop_count_force_val = hop_count_val;
733 }
734
735 nan_enable_request(0, global_handle, &req);
736
737 /* Start the config of fam */
738
739 memset(&configReq, 0, sizeof(NanConfigRequest));
740 configReq.header.handle = 0x0;
741 configReq.header.transaction_id = 0;
742
743 configReq.config_fam = 1;
744 configReq.fam_val.numchans = 1;
745 configReq.fam_val.entry_control = 0;
746 configReq.fam_val.class_val = 81;
747 configReq.fam_val.channel = 6;
748 configReq.fam_val.mapid = 0;
749 configReq.fam_val.avail_interval_bitmap = 0x7ffffffe;
750 configReq.fam_val.vendor_elements_len = 0;
751 memset(&configReq.fam_val.vendor_elements[0], 0,
752 sizeof(configReq.fam_val.vendor_elements));
753 nan_config_request(0, global_handle, &configReq);
754
755 return 0;
756}
757
758
759int sigma_nan_transmit_followup(struct sigma_dut *dut,
760 struct sigma_conn *conn,
761 struct sigma_cmd *cmd)
762{
763 const char *mac = get_param(cmd, "mac");
764 const char *requestor_id = get_param(cmd, "RemoteInstanceId");
765 const char *local_id = get_param(cmd, "LocalInstanceId");
766 const char *service_name = get_param(cmd, "servicename");
767 NanTransmitFollowupRequest req;
768
769 memset(&req, 0, sizeof(NanTransmitFollowupRequest));
770 req.header.handle = (uint16_t)global_header_handle;
771 req.header.transaction_id = 0;
772 req.match_handle = global_match_handle;
773 req.addr[0] = 0xFF;
774 req.addr[1] = 0xFF;
775 req.addr[2] = 0xFF;
776 req.addr[3] = 0xFF;
777 req.addr[4] = 0xFF;
778 req.addr[5] = 0xFF;
779 req.priority = NAN_TX_PRIORITY_NORMAL;
780 req.dw_or_faw = 0;
781 req.service_specific_info_len = strlen(service_name);
782
783 if (requestor_id) {
784 /* int requestor_id_val = atoi(requestor_id); */
785 req.match_handle = global_match_handle;
786 }
787 if (local_id) {
788 /* int local_id_val = atoi(local_id); */
789 req.header.handle = global_header_handle;
790 }
791
792 if (mac == NULL) {
793 sigma_dut_print(dut, DUT_MSG_ERROR, "Invalid MAC Address");
794 return -1;
795 }
796 nan_parse_mac_address(dut, mac, req.addr);
797
798#if 0
799 if (requestor_id)
800 req.match_handle = strtoul(requestor_id, NULL, 0);
801#endif
802
803 nan_transmit_followup_request(0, global_handle, &req);
804 return 0;
805}
806
807/* NotifyResponse invoked to notify the status of the Request */
808void nan_notify_response(NanResponseMsg *rsp_data)
809{
810 sigma_dut_print(global_dut, DUT_MSG_INFO,
811 "%s: handle %d status %d value %d response_type %d",
812 __func__, rsp_data->header.handle,
813 rsp_data->status, rsp_data->value,
814 rsp_data->response_type);
815 global_header_handle = rsp_data->header.handle;
816 if (rsp_data->response_type == NAN_RESPONSE_STATS) {
817 sigma_dut_print(global_dut, DUT_MSG_INFO, "%s: stats_id %d",
818 __func__,
819 rsp_data->body.stats_response.stats_id);
820 }
821#if 0
822 if (rsp_data->response_type == NAN_RESPONSE_CONFIG &&
823 rsp_data->status == 0)
824 pthread_cond_signal(&gCondition);
825#endif
826}
827
828
829/* Events Callback */
830void nan_event_publish_replied(NanPublishRepliedInd *event)
831{
832 sigma_dut_print(global_dut, DUT_MSG_INFO,
833 "%s: handle %d " MAC_ADDR_STR " rssi:%d",
834 __func__, event->header.handle,
835 MAC_ADDR_ARRAY(event->addr), event->rssi_value);
836 event_anyresponse = 1;
837 snprintf(global_event_resp_buf, sizeof(global_event_resp_buf),
838 "EventName,Replied,RemoteInstanceId %d,mac," MAC_ADDR_STR,
839 event->header.handle, MAC_ADDR_ARRAY(event->addr));
840}
841
842
843/* Events Callback */
844void nan_event_publish_terminated(NanPublishTerminatedInd *event)
845{
846 sigma_dut_print(global_dut, DUT_MSG_INFO, "%s: handle %d reason %d",
847 __func__, event->header.handle, event->reason);
848}
849
850
851/* Events Callback */
852void nan_event_match(NanMatchInd *event)
853{
854 sigma_dut_print(global_dut, DUT_MSG_INFO,
855 "%s: handle %d match_handle %08x " MAC_ADDR_STR
856 " rssi:%d",
857 __func__,
858 event->header.handle,
859 event->match_handle,
860 MAC_ADDR_ARRAY(event->addr),
861 event->rssi_value);
862 event_anyresponse = 1;
863 global_header_handle = event->header.handle;
864 global_match_handle = event->match_handle;
865 /* memset(event_resp_buf, 0, sizeof(event_resp_buf)); */
866 /* global_pub_sub_handle = event->header.handle; */
867 /* Print the SSI */
868 sigma_dut_print(global_dut, DUT_MSG_INFO, "Printing SSI:");
869#if 0
870 nanhexdump(event->service_specific_info,
871 event->service_specific_info_len);
872#endif
873 snprintf(global_event_resp_buf, sizeof(global_event_resp_buf),
874 "EventName,DiscoveryResult,RemoteInstanceID,%d,LocalInstanceID,%d,mac,"
875 MAC_ADDR_STR " ", (event->match_handle >> 24),
876 event->header.handle, MAC_ADDR_ARRAY(event->addr));
877
878 /* Print the match filter */
879 sigma_dut_print(global_dut, DUT_MSG_INFO, "Printing sdf match filter:");
880 /* nanhexdump(event->sdf_match_filter, event->sdf_match_filter_len); */
881
882 /* Print the conn_capability */
883 sigma_dut_print(global_dut, DUT_MSG_INFO,
884 "Printing PostConnectivity Capability");
885 if (event->is_conn_capability_valid) {
886 sigma_dut_print(global_dut, DUT_MSG_INFO, "Wfd supported:%s",
887 event->conn_capability.is_wfd_supported ?
888 "yes" : "no");
889 sigma_dut_print(global_dut, DUT_MSG_INFO, "Wfds supported:%s",
890 (event->conn_capability.is_wfds_supported ?
891 "yes" : "no"));
892 sigma_dut_print(global_dut, DUT_MSG_INFO, "TDLS supported:%s",
893 (event->conn_capability.is_tdls_supported ?
894 "yes" : "no"));
895 sigma_dut_print(global_dut, DUT_MSG_INFO, "IBSS supported:%s",
896 (event->conn_capability.is_ibss_supported ?
897 "yes" : "no"));
898 sigma_dut_print(global_dut, DUT_MSG_INFO, "Mesh supported:%s",
899 (event->conn_capability.is_mesh_supported ?
900 "yes" : "no"));
901 sigma_dut_print(global_dut, DUT_MSG_INFO, "Infra Field:%d",
902 event->conn_capability.wlan_infra_field);
903 } else {
904 sigma_dut_print(global_dut, DUT_MSG_INFO,
905 "PostConnectivity Capability not present");
906 }
907
908 /* Print the discovery_attr */
909 sigma_dut_print(global_dut, DUT_MSG_INFO,
910 "Printing PostDiscovery Attribute");
911 if (event->is_discovery_attr_valid) {
912 sigma_dut_print(global_dut, DUT_MSG_INFO,
913 "Conn Type:%d Device Role:%d"
914 MAC_ADDR_STR,
915 event->discovery_attr.type,
916 event->discovery_attr.role,
917 MAC_ADDR_ARRAY(event->discovery_attr.addr));
918 /* nanPrintFurtherAvailabilityMap(&event->discovery_attr.fam);
919 */
920 sigma_dut_print(global_dut, DUT_MSG_INFO,
921 "Printing Mesh Id:");
922#if 0
923 nanhexdump(event->discovery_attr.mesh_id,
924 sizeof(event->discovery_attr.mesh_id));
925#endif
926 } else {
927 sigma_dut_print(global_dut, DUT_MSG_INFO,
928 "PostDiscovery attribute not present");
929 }
930
931 /* Print the fam */
932 if (event->is_fam_valid) {
933 /* nanPrintFurtherAvailabilityMap(&event->fam); */
934 }
935}
936
937
938/* Events Callback */
939void nan_event_unmatch(NanUnmatchInd *event)
940{
941 sigma_dut_print(global_dut, DUT_MSG_INFO,
942 "%s: handle %d match_handle %08x",
943 __func__, event->header.handle, event->match_handle);
944}
945
946
947/* Events Callback */
948void nan_event_subscribe_terminated(NanSubscribeTerminatedInd *event)
949{
950 sigma_dut_print(global_dut, DUT_MSG_INFO, "%s: handle %d reason %d",
951 __func__, event->header.handle, event->reason);
952}
953
954
955/* Events Callback */
956void nan_event_followup(NanFollowupInd *event)
957{
958 sigma_dut_print(global_dut, DUT_MSG_INFO,
959 "%s: handle %d match_handle 0x%08x dw_or_faw %d "
960 MAC_ADDR_STR, __func__, event->header.handle,
961 event->match_handle, event->dw_or_faw,
962 MAC_ADDR_ARRAY(event->addr));
963
964 global_match_handle = event->match_handle;
965 global_header_handle = event->header.handle;
966#if 0
967 nanhexdump(event->service_specific_info,
968 event->service_specific_info_len);
969#endif
970 event_anyresponse = 1;
971 snprintf(global_event_resp_buf, sizeof(global_event_resp_buf),
972 "EventName,FollowUp,RemoteInstanceID,%d,LocalInstanceID,%d,mac,"
973 MAC_ADDR_STR " ", event->match_handle >> 24,
974 event->header.handle, MAC_ADDR_ARRAY(event->addr));
975}
976
977
978/* Events Callback */
979void nan_event_disceng_event(NanDiscEngEventInd *event)
980{
981 sigma_dut_print(global_dut, DUT_MSG_INFO, "%s: handle %d event_id %d",
982 __func__, event->header.handle, event->event_id);
983
984 if (event->event_id == NAN_EVENT_ID_JOINED_CLUSTER) {
985 sigma_dut_print(global_dut, DUT_MSG_INFO, "%s: Joined cluster "
986 MAC_ADDR_STR,
987 __func__,
988 MAC_ADDR_ARRAY(event->data.cluster.addr));
989 }
990 if (event->event_id == NAN_EVENT_ID_STARTED_CLUSTER) {
991 sigma_dut_print(global_dut, DUT_MSG_INFO,
992 "%s: Started cluster " MAC_ADDR_STR,
993 __func__,
994 MAC_ADDR_ARRAY(event->data.cluster.addr));
995 }
996 if (event->event_id == NAN_EVENT_ID_STA_MAC_ADDR) {
997 sigma_dut_print(global_dut, DUT_MSG_INFO, "%s: Self STA "
998 MAC_ADDR_STR,
999 __func__,
1000 MAC_ADDR_ARRAY(event->data.mac_addr.addr));
1001 memcpy(global_nan_mac_addr, event->data.mac_addr.addr,
1002 sizeof(global_nan_mac_addr));
1003 }
1004 pthread_cond_signal(&gCondition);
1005}
1006
1007
1008/* Events Callback */
1009void nan_event_disabled(NanDisabledInd *event)
1010{
1011 sigma_dut_print(global_dut, DUT_MSG_INFO, "%s: handle %d reason %d",
1012 __func__, event->header.handle, event->reason);
1013 /* pthread_cond_signal(&gCondition); */
1014}
1015
1016
1017void * my_thread_function(void *ptr)
1018{
1019 wifi_event_loop(global_handle);
1020 pthread_exit(0);
1021 return (void *) NULL;
1022}
1023
1024
1025static NanCallbackHandler callbackHandler = {
1026 .NotifyResponse = nan_notify_response,
1027 .EventPublishReplied = nan_event_publish_replied,
1028 .EventPublishTerminated = nan_event_publish_terminated,
1029 .EventMatch = nan_event_match,
1030 .EventUnMatch = nan_event_unmatch,
1031 .EventSubscribeTerminated = nan_event_subscribe_terminated,
1032 .EventFollowup = nan_event_followup,
1033 .EventDiscEngEvent = nan_event_disceng_event,
1034 .EventDisabled = nan_event_disabled,
1035};
1036
1037void nan_init(struct sigma_dut *dut)
1038{
1039 pthread_t thread1; /* thread variables */
1040 wifi_error err = wifi_initialize(&global_handle);
1041
1042 if (err) {
1043 printf("wifi hal initialize failed\n");
1044 return;
1045 }
1046
1047 /* create threads 1 */
1048 pthread_create(&thread1, NULL, &my_thread_function, NULL);
1049
1050 pthread_mutex_init(&gMutex, NULL);
1051 pthread_cond_init(&gCondition, NULL);
1052
1053 nan_register_handler(global_handle, callbackHandler);
1054}
1055
1056
1057void nan_cmd_sta_reset_default(struct sigma_dut *dut, struct sigma_conn *conn,
1058 struct sigma_cmd *cmd)
1059{
1060 sigma_dut_print(dut, DUT_MSG_INFO, "NAN sta_reset_default");
1061
1062 if (nan_state == 0) {
1063 nan_init(dut);
1064 nan_state = 1;
1065 }
1066 is_fam = 0;
1067 event_anyresponse = 0;
1068 global_dut = dut;
1069 memset(global_event_resp_buf, 0, sizeof(global_event_resp_buf));
1070 sigma_nan_disable(dut, conn, cmd);
1071}
1072
1073
1074int nan_cmd_sta_exec_action(struct sigma_dut *dut, struct sigma_conn *conn,
1075 struct sigma_cmd *cmd)
1076{
1077 const char *program = get_param(cmd, "Prog");
1078 const char *nan_op = get_param(cmd, "NANOp");
1079 const char *method_type = get_param(cmd, "MethodType");
1080 char resp_buf[100];
1081
1082 if (program == NULL)
1083 return -1;
1084
1085 if (strcasecmp(program, "NAN") != 0) {
1086 send_resp(dut, conn, SIGMA_ERROR,
1087 "ErrorCode,Unsupported program");
1088 return 0;
1089 }
1090
1091 if (nan_op) {
1092 /*
1093 * NANOp has been specified.
1094 * We will build a nan_enable or nan_disable command.
1095 */
1096 if (strcasecmp(nan_op, "On") == 0) {
1097 if (sigma_nan_enable(dut, conn, cmd) == 0) {
1098 snprintf(resp_buf, sizeof(resp_buf), "mac,"
1099 MAC_ADDR_STR,
1100 MAC_ADDR_ARRAY(global_nan_mac_addr));
1101 send_resp(dut, conn, SIGMA_COMPLETE, resp_buf);
1102 } else {
1103 send_resp(dut, conn, SIGMA_ERROR,
1104 "NAN_ENABLE_FAILED");
1105 return -1;
1106 }
1107 } else if (strcasecmp(nan_op, "Off") == 0) {
1108 sigma_nan_disable(dut, conn, cmd);
1109 send_resp(dut, conn, SIGMA_COMPLETE, "NULL");
1110 }
1111 }
1112 if (nan_state && nan_op == NULL) {
1113 if (method_type) {
1114 if (strcasecmp(method_type, "Publish") == 0) {
1115 sigma_nan_publish_request(dut, conn, cmd);
1116 send_resp(dut, conn, SIGMA_COMPLETE, "NULL");
1117 }
1118 if (strcasecmp(method_type, "Subscribe") == 0) {
1119 sigma_nan_subscribe_request(dut, conn, cmd);
1120 send_resp(dut, conn, SIGMA_COMPLETE, "NULL");
1121 }
1122 if (strcasecmp(method_type, "Followup") == 0) {
1123 sigma_nan_transmit_followup(dut, conn, cmd);
1124 send_resp(dut, conn, SIGMA_COMPLETE, "NULL");
1125 }
1126 } else {
1127 sigma_nan_config_enable(dut, conn, cmd);
1128 snprintf(resp_buf, sizeof(resp_buf), "mac,"
1129 MAC_ADDR_STR,
1130 MAC_ADDR_ARRAY(global_nan_mac_addr));
1131 send_resp(dut, conn, SIGMA_COMPLETE, resp_buf);
1132 }
1133 }
1134
1135 return 0;
1136}
1137
1138
1139int nan_cmd_sta_get_parameter(struct sigma_dut *dut, struct sigma_conn *conn,
1140 struct sigma_cmd *cmd)
1141{
1142
1143 const char *program = get_param(cmd, "Program");
1144 const char *parameter = get_param(cmd, "Parameter");
1145 char resp_buf[100];
1146 NanStaParameter rsp;
1147
1148 if (program == NULL) {
1149 sigma_dut_print(dut, DUT_MSG_ERROR, "Invalid Program Name");
1150 return -1;
1151 }
1152 if (strcasecmp(program, "NAN") != 0) {
1153 send_resp(dut, conn, SIGMA_ERROR,
1154 "ErrorCode,Unsupported program");
1155 return 0;
1156 }
1157
1158 if (parameter == NULL) {
1159 sigma_dut_print(dut, DUT_MSG_ERROR, "Invalid Parameter");
1160 return -1;
1161 }
1162 memset(&rsp, 0, sizeof(NanStaParameter));
1163
1164 nan_get_sta_parameter(0, global_handle, &rsp);
1165 sigma_dut_print(dut, DUT_MSG_INFO,
1166 "%s: NanStaparameter Master_pref:%02x, Random_factor:%02x, hop_count:%02x beacon_transmit_time:%d",
1167 __func__, rsp.master_pref, rsp.random_factor,
1168 rsp.hop_count, rsp.beacon_transmit_time);
1169
1170 if (strcasecmp(parameter, "MasterPref") == 0) {
1171 snprintf(resp_buf, sizeof(resp_buf), "MasterPref,0x%x",
1172 rsp.master_pref);
1173 } else if (strcasecmp(parameter, "MasterRank") == 0) {
1174 snprintf(resp_buf, sizeof(resp_buf), "MasterRank,0x%lx",
1175 rsp.master_rank);
1176 } else if (strcasecmp(parameter, "RandFactor") == 0) {
1177 snprintf(resp_buf, sizeof(resp_buf), "RandFactor,0x%x",
1178 rsp.random_factor);
1179 } else if (strcasecmp(parameter, "HopCount") == 0) {
1180 snprintf(resp_buf, sizeof(resp_buf), "HopCount,0x%x",
1181 rsp.hop_count);
1182 } else if (strcasecmp(parameter, "BeaconTransTime") == 0) {
1183 snprintf(resp_buf, sizeof(resp_buf), "BeaconTransTime 0x%x",
1184 rsp.beacon_transmit_time);
1185 } else if (strcasecmp(parameter, "NANStatus") == 0) {
1186 if (nan_state == 1)
1187 snprintf(resp_buf, sizeof(resp_buf), "On");
1188 else
1189 snprintf(resp_buf, sizeof(resp_buf), "Off");
1190 } else {
1191 send_resp(dut, conn, SIGMA_ERROR, "Invalid Parameter");
1192 return 0;
1193 }
1194
1195 send_resp(dut, conn, SIGMA_COMPLETE, resp_buf);
1196 return 0;
1197}
1198
1199
1200int nan_cmd_sta_get_events(struct sigma_dut *dut, struct sigma_conn *conn,
1201 struct sigma_cmd *cmd)
1202{
1203 const char *action = get_param(cmd, "Action");
1204
1205 /* Check action for start, stop and get events. */
1206 if (strcasecmp(action, "Start") == 0) {
1207 memset(global_event_resp_buf, 0, sizeof(global_event_resp_buf));
1208 send_resp(dut, conn, SIGMA_COMPLETE, NULL);
1209 } else if (strcasecmp(action, "Stop") == 0) {
1210 event_anyresponse = 0;
1211 memset(global_event_resp_buf, 0, sizeof(global_event_resp_buf));
1212 send_resp(dut, conn, SIGMA_COMPLETE, NULL);
1213 } else if (strcasecmp(action, "Get") == 0) {
1214 if (event_anyresponse == 1) {
1215 send_resp(dut, conn, SIGMA_COMPLETE,
1216 global_event_resp_buf);
1217 } else {
1218 send_resp(dut, conn, SIGMA_COMPLETE, "EventList,NONE");
1219 }
1220 }
1221 return 0;
1222}