1 /* 2 * Sigma Control API DUT (NAN functionality) 3 * Copyright (c) 2014-2017, 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_cert.h" 14 15 #if NAN_CERT_VERSION >= 2 16 17 pthread_cond_t gCondition; 18 pthread_mutex_t gMutex; 19 wifi_handle global_wifi_handle; 20 wifi_interface_handle global_interface_handle; 21 static NanSyncStats global_nan_sync_stats; 22 static int nan_state = 0; 23 static int event_anyresponse = 0; 24 static int is_fam = 0; 25 26 static uint16_t global_ndp_instance_id = 0; 27 static uint16_t global_publish_id = 0; 28 static uint16_t global_subscribe_id = 0; 29 uint16_t global_header_handle = 0; 30 uint32_t global_match_handle = 0; 31 32 #define DEFAULT_SVC "QNanCluster" 33 #define MAC_ADDR_ARRAY(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] 34 #define MAC_ADDR_STR "%02x:%02x:%02x:%02x:%02x:%02x" 35 #ifndef ETH_ALEN 36 #define ETH_ALEN 6 37 #endif 38 39 struct sigma_dut *global_dut = NULL; 40 static char global_nan_mac_addr[ETH_ALEN]; 41 static char global_peer_mac_addr[ETH_ALEN]; 42 static char global_event_resp_buf[1024]; 43 static u8 global_publish_service_name[NAN_MAX_SERVICE_NAME_LEN]; 44 static u32 global_publish_service_name_len = 0; 45 46 static int nan_further_availability_tx(struct sigma_dut *dut, 47 struct sigma_conn *conn, 48 struct sigma_cmd *cmd); 49 static int nan_further_availability_rx(struct sigma_dut *dut, 50 struct sigma_conn *conn, 51 struct sigma_cmd *cmd); 52 53 54 void nan_hex_dump(struct sigma_dut *dut, uint8_t *data, size_t len) 55 { 56 char buf[512]; 57 uint16_t index; 58 uint8_t *ptr; 59 int pos; 60 61 memset(buf, 0, sizeof(buf)); 62 ptr = data; 63 pos = 0; 64 for (index = 0; index < len; index++) { 65 pos += sprintf(&(buf[pos]), "%02x ", *ptr++); 66 if (pos > 508) 67 break; 68 } 69 sigma_dut_print(dut, DUT_MSG_INFO, "HEXDUMP len=[%d]", (int) len); 70 sigma_dut_print(dut, DUT_MSG_INFO, "buf:%s", buf); 71 } 72 73 74 int nan_parse_hex(unsigned char c) 75 { 76 if (c >= '0' && c <= '9') 77 return c - '0'; 78 if (c >= 'a' && c <= 'f') 79 return c - 'a' + 10; 80 if (c >= 'A' && c <= 'F') 81 return c - 'A' + 10; 82 return 0; 83 } 84 85 86 int nan_parse_token(const char *tokenIn, u8 *tokenOut, int *filterLen) 87 { 88 int total_len = 0, len = 0; 89 char *saveptr = NULL; 90 91 tokenIn = strtok_r((char *) tokenIn, ":", &saveptr); 92 while (tokenIn != NULL) { 93 len = strlen(tokenIn); 94 if (len == 1 && *tokenIn == '*') 95 len = 0; 96 tokenOut[total_len++] = (u8) len; 97 if (len != 0) 98 memcpy((u8 *) tokenOut + total_len, tokenIn, len); 99 total_len += len; 100 tokenIn = strtok_r(NULL, ":", &saveptr); 101 } 102 *filterLen = total_len; 103 return 0; 104 } 105 106 107 int nan_parse_mac_address(struct sigma_dut *dut, const char *arg, u8 *addr) 108 { 109 if (strlen(arg) != 17) { 110 sigma_dut_print(dut, DUT_MSG_ERROR, "Invalid mac address %s", 111 arg); 112 sigma_dut_print(dut, DUT_MSG_ERROR, 113 "expected format xx:xx:xx:xx:xx:xx"); 114 return -1; 115 } 116 117 addr[0] = nan_parse_hex(arg[0]) << 4 | nan_parse_hex(arg[1]); 118 addr[1] = nan_parse_hex(arg[3]) << 4 | nan_parse_hex(arg[4]); 119 addr[2] = nan_parse_hex(arg[6]) << 4 | nan_parse_hex(arg[7]); 120 addr[3] = nan_parse_hex(arg[9]) << 4 | nan_parse_hex(arg[10]); 121 addr[4] = nan_parse_hex(arg[12]) << 4 | nan_parse_hex(arg[13]); 122 addr[5] = nan_parse_hex(arg[15]) << 4 | nan_parse_hex(arg[16]); 123 124 return 0; 125 } 126 127 128 int nan_parse_mac_address_list(struct sigma_dut *dut, const char *input, 129 u8 *output, u16 max_addr_allowed) 130 { 131 /* 132 * Reads a list of mac address separated by space. Each MAC address 133 * should have the format of aa:bb:cc:dd:ee:ff. 134 */ 135 char *saveptr; 136 char *token; 137 int i = 0; 138 139 for (i = 0; i < max_addr_allowed; i++) { 140 token = strtok_r((i == 0) ? (char *) input : NULL, 141 " ", &saveptr); 142 if (token) { 143 nan_parse_mac_address(dut, token, output); 144 output += NAN_MAC_ADDR_LEN; 145 } else 146 break; 147 } 148 149 sigma_dut_print(dut, DUT_MSG_INFO, "Num MacAddress:%d", i); 150 151 return i; 152 } 153 154 155 int nan_parse_hex_string(struct sigma_dut *dut, const char *input, 156 u8 *output, int *outputlen) 157 { 158 int i = 0; 159 int j = 0; 160 161 for (i = 0; i < (int) strlen(input) && j < *outputlen; i += 2) { 162 output[j] = nan_parse_hex(input[i]); 163 if (i + 1 < (int) strlen(input)) { 164 output[j] = ((output[j] << 4) | 165 nan_parse_hex(input[i + 1])); 166 } 167 j++; 168 } 169 *outputlen = j; 170 sigma_dut_print(dut, DUT_MSG_INFO, "Input:%s inputlen:%d outputlen:%d", 171 input, (int) strlen(input), (int) *outputlen); 172 return 0; 173 } 174 175 176 int wait(struct timespec abstime) 177 { 178 struct timeval now; 179 180 gettimeofday(&now, NULL); 181 182 abstime.tv_sec += now.tv_sec; 183 if (((abstime.tv_nsec + now.tv_usec * 1000) > 1000 * 1000 * 1000) || 184 (abstime.tv_nsec + now.tv_usec * 1000 < 0)) { 185 abstime.tv_sec += 1; 186 abstime.tv_nsec += now.tv_usec * 1000; 187 abstime.tv_nsec -= 1000 * 1000 * 1000; 188 } else { 189 abstime.tv_nsec += now.tv_usec * 1000; 190 } 191 192 return pthread_cond_timedwait(&gCondition, &gMutex, &abstime); 193 } 194 195 196 int nan_cmd_sta_preset_testparameters(struct sigma_dut *dut, 197 struct sigma_conn *conn, 198 struct sigma_cmd *cmd) 199 { 200 const char *oper_chan = get_param(cmd, "oper_chn"); 201 const char *pmk = get_param(cmd, "PMK"); 202 203 if (oper_chan) { 204 sigma_dut_print(dut, DUT_MSG_INFO, "Operating Channel: %s", 205 oper_chan); 206 dut->sta_channel = atoi(oper_chan); 207 } 208 209 if (pmk) { 210 int pmk_len; 211 212 sigma_dut_print(dut, DUT_MSG_INFO, "%s given string pmk: %s", 213 __func__, pmk); 214 memset(dut->nan_pmk, 0, NAN_PMK_INFO_LEN); 215 dut->nan_pmk_len = 0; 216 pmk_len = NAN_PMK_INFO_LEN; 217 nan_parse_hex_string(dut, &pmk[2], &dut->nan_pmk[0], &pmk_len); 218 dut->nan_pmk_len = pmk_len; 219 sigma_dut_print(dut, DUT_MSG_INFO, "%s: pmk len = %d", 220 __func__, dut->nan_pmk_len); 221 sigma_dut_print(dut, DUT_MSG_INFO, "%s:hex pmk", __func__); 222 nan_hex_dump(dut, &dut->nan_pmk[0], dut->nan_pmk_len); 223 } 224 225 send_resp(dut, conn, SIGMA_COMPLETE, NULL); 226 return 0; 227 } 228 229 230 void nan_print_further_availability_chan(struct sigma_dut *dut, 231 u8 num_chans, 232 NanFurtherAvailabilityChannel *fachan) 233 { 234 int idx; 235 236 sigma_dut_print(dut, DUT_MSG_INFO, 237 "********Printing FurtherAvailabilityChan Info******"); 238 sigma_dut_print(dut, DUT_MSG_INFO, "Numchans:%d", num_chans); 239 for (idx = 0; idx < num_chans; idx++) { 240 sigma_dut_print(dut, DUT_MSG_INFO, 241 "[%d]: NanAvailDuration:%d class_val:%02x channel:%d", 242 idx, fachan->entry_control, 243 fachan->class_val, fachan->channel); 244 sigma_dut_print(dut, DUT_MSG_INFO, 245 "[%d]: mapid:%d Availability bitmap:%08x", 246 idx, fachan->mapid, 247 fachan->avail_interval_bitmap); 248 } 249 sigma_dut_print(dut, DUT_MSG_INFO, 250 "*********************Done**********************"); 251 } 252 253 254 int sigma_nan_enable(struct sigma_dut *dut, struct sigma_conn *conn, 255 struct sigma_cmd *cmd) 256 { 257 const char *master_pref = get_param(cmd, "MasterPref"); 258 const char *rand_fac = get_param(cmd, "RandFactor"); 259 const char *hop_count = get_param(cmd, "HopCount"); 260 const char *high_tsf = get_param(cmd, "HighTSF"); 261 const char *sdftx_band = get_param(cmd, "SDFTxBand"); 262 const char *oper_chan = get_param(cmd, "oper_chn"); 263 const char *further_avail_ind = get_param(cmd, "FurtherAvailInd"); 264 const char *band = get_param(cmd, "Band"); 265 const char *only_5g = get_param(cmd, "5GOnly"); 266 const char *nan_availability = get_param(cmd, "NANAvailability"); 267 struct timespec abstime; 268 NanEnableRequest req; 269 270 memset(&req, 0, sizeof(NanEnableRequest)); 271 req.cluster_low = 0; 272 req.cluster_high = 0xFFFF; 273 req.master_pref = 100; 274 275 /* This is a debug hack to beacon in channel 11 */ 276 if (oper_chan) { 277 req.config_2dot4g_support = 1; 278 req.support_2dot4g_val = 111; 279 } 280 281 if (master_pref) { 282 int master_pref_val = strtoul(master_pref, NULL, 0); 283 284 req.master_pref = master_pref_val; 285 } 286 287 if (rand_fac) { 288 int rand_fac_val = strtoul(rand_fac, NULL, 0); 289 290 req.config_random_factor_force = 1; 291 req.random_factor_force_val = rand_fac_val; 292 } 293 294 if (hop_count) { 295 int hop_count_val = strtoul(hop_count, NULL, 0); 296 297 req.config_hop_count_force = 1; 298 req.hop_count_force_val = hop_count_val; 299 } 300 301 if (sdftx_band) { 302 if (strcasecmp(sdftx_band, "5G") == 0) { 303 req.config_2dot4g_support = 1; 304 req.support_2dot4g_val = 0; 305 } 306 } 307 308 sigma_dut_print(dut, DUT_MSG_INFO, 309 "%s: Setting dual band 2.4 GHz and 5 GHz by default", 310 __func__); 311 /* Enable 2.4 GHz support */ 312 req.config_2dot4g_support = 1; 313 req.support_2dot4g_val = 1; 314 req.config_2dot4g_beacons = 1; 315 req.beacon_2dot4g_val = 1; 316 req.config_2dot4g_sdf = 1; 317 req.sdf_2dot4g_val = 1; 318 319 /* Enable 5 GHz support */ 320 req.config_support_5g = 1; 321 req.support_5g_val = 1; 322 req.config_5g_beacons = 1; 323 req.beacon_5g_val = 1; 324 req.config_5g_sdf = 1; 325 req.sdf_5g_val = 1; 326 327 if (band) { 328 if (strcasecmp(band, "24G") == 0) { 329 sigma_dut_print(dut, DUT_MSG_INFO, 330 "Band 2.4 GHz selected, disable 5 GHz"); 331 /* Disable 5G support */ 332 req.config_support_5g = 1; 333 req.support_5g_val = 0; 334 req.config_5g_beacons = 1; 335 req.beacon_5g_val = 0; 336 req.config_5g_sdf = 1; 337 req.sdf_5g_val = 0; 338 } 339 } 340 341 if (further_avail_ind) { 342 sigma_dut_print(dut, DUT_MSG_INFO, "FAM Test Enabled"); 343 if (strcasecmp(further_avail_ind, "tx") == 0) { 344 is_fam = 1; 345 nan_further_availability_tx(dut, conn, cmd); 346 return 0; 347 } else if (strcasecmp(further_avail_ind, "rx") == 0) { 348 nan_further_availability_rx(dut, conn, cmd); 349 return 0; 350 } 351 } 352 353 if (only_5g && atoi(only_5g)) { 354 sigma_dut_print(dut, DUT_MSG_INFO, "5GHz only enabled"); 355 req.config_2dot4g_support = 1; 356 req.support_2dot4g_val = 1; 357 req.config_2dot4g_beacons = 1; 358 req.beacon_2dot4g_val = 0; 359 req.config_2dot4g_sdf = 1; 360 req.sdf_2dot4g_val = 1; 361 } 362 363 nan_enable_request(0, global_interface_handle, &req); 364 365 if (nan_availability) { 366 int cmd_len, size; 367 NanDebugParams cfg_debug; 368 369 sigma_dut_print(dut, DUT_MSG_INFO, 370 "%s given string nan_availability: %s", 371 __func__, nan_availability); 372 memset(&cfg_debug, 0, sizeof(NanDebugParams)); 373 cfg_debug.cmd = NAN_TEST_MODE_CMD_NAN_AVAILABILITY; 374 size = NAN_MAX_DEBUG_MESSAGE_DATA_LEN; 375 nan_parse_hex_string(dut, &nan_availability[2], 376 &cfg_debug.debug_cmd_data[0], &size); 377 sigma_dut_print(dut, DUT_MSG_INFO, "%s:hex nan_availability", 378 __func__); 379 nan_hex_dump(dut, &cfg_debug.debug_cmd_data[0], size); 380 cmd_len = size + sizeof(u32); 381 nan_debug_command_config(0, global_interface_handle, 382 cfg_debug, cmd_len); 383 } 384 385 /* To ensure sta_get_events to get the events 386 * only after joining the NAN cluster. */ 387 abstime.tv_sec = 30; 388 abstime.tv_nsec = 0; 389 wait(abstime); 390 391 return 0; 392 } 393 394 395 int sigma_nan_disable(struct sigma_dut *dut, struct sigma_conn *conn, 396 struct sigma_cmd *cmd) 397 { 398 struct timespec abstime; 399 400 nan_disable_request(0, global_interface_handle); 401 402 abstime.tv_sec = 4; 403 abstime.tv_nsec = 0; 404 wait(abstime); 405 406 return 0; 407 } 408 409 410 int sigma_nan_config_enable(struct sigma_dut *dut, struct sigma_conn *conn, 411 struct sigma_cmd *cmd) 412 { 413 const char *master_pref = get_param(cmd, "MasterPref"); 414 const char *rand_fac = get_param(cmd, "RandFactor"); 415 const char *hop_count = get_param(cmd, "HopCount"); 416 wifi_error ret; 417 struct timespec abstime; 418 NanConfigRequest req; 419 420 memset(&req, 0, sizeof(NanConfigRequest)); 421 req.config_rssi_proximity = 1; 422 req.rssi_proximity = 70; 423 424 if (master_pref) { 425 int master_pref_val = strtoul(master_pref, NULL, 0); 426 427 req.config_master_pref = 1; 428 req.master_pref = master_pref_val; 429 } 430 431 if (rand_fac) { 432 int rand_fac_val = strtoul(rand_fac, NULL, 0); 433 434 req.config_random_factor_force = 1; 435 req.random_factor_force_val = rand_fac_val; 436 } 437 438 if (hop_count) { 439 int hop_count_val = strtoul(hop_count, NULL, 0); 440 441 req.config_hop_count_force = 1; 442 req.hop_count_force_val = hop_count_val; 443 } 444 445 ret = nan_config_request(0, global_interface_handle, &req); 446 if (ret != WIFI_SUCCESS) 447 send_resp(dut, conn, SIGMA_ERROR, "NAN config request failed"); 448 449 abstime.tv_sec = 4; 450 abstime.tv_nsec = 0; 451 wait(abstime); 452 453 return 0; 454 } 455 456 457 static int sigma_nan_subscribe_request(struct sigma_dut *dut, 458 struct sigma_conn *conn, 459 struct sigma_cmd *cmd) 460 { 461 const char *subscribe_type = get_param(cmd, "SubscribeType"); 462 const char *service_name = get_param(cmd, "ServiceName"); 463 const char *disc_range = get_param(cmd, "DiscoveryRange"); 464 const char *rx_match_filter = get_param(cmd, "rxMatchFilter"); 465 const char *tx_match_filter = get_param(cmd, "txMatchFilter"); 466 const char *sdftx_dw = get_param(cmd, "SDFTxDW"); 467 const char *discrange_ltd = get_param(cmd, "DiscRangeLtd"); 468 const char *include_bit = get_param(cmd, "IncludeBit"); 469 const char *mac = get_param(cmd, "MAC"); 470 const char *srf_type = get_param(cmd, "SRFType"); 471 const char *awake_dw_interval = get_param(cmd, "awakeDWint"); 472 NanSubscribeRequest req; 473 NanConfigRequest config_req; 474 int filter_len_rx = 0, filter_len_tx = 0; 475 u8 input_rx[NAN_MAX_MATCH_FILTER_LEN]; 476 u8 input_tx[NAN_MAX_MATCH_FILTER_LEN]; 477 wifi_error ret; 478 479 memset(&req, 0, sizeof(NanSubscribeRequest)); 480 memset(&config_req, 0, sizeof(NanConfigRequest)); 481 req.ttl = 0; 482 req.period = 1; 483 req.subscribe_type = 1; 484 req.serviceResponseFilter = 1; /* MAC */ 485 req.serviceResponseInclude = 0; 486 req.ssiRequiredForMatchIndication = 0; 487 req.subscribe_match_indicator = NAN_MATCH_ALG_MATCH_CONTINUOUS; 488 req.subscribe_count = 0; 489 490 if (subscribe_type) { 491 if (strcasecmp(subscribe_type, "Active") == 0) { 492 req.subscribe_type = 1; 493 } else if (strcasecmp(subscribe_type, "Passive") == 0) { 494 req.subscribe_type = 0; 495 } else if (strcasecmp(subscribe_type, "Cancel") == 0) { 496 NanSubscribeCancelRequest req; 497 498 memset(&req, 0, sizeof(NanSubscribeCancelRequest)); 499 ret = nan_subscribe_cancel_request( 500 0, global_interface_handle, &req); 501 if (ret != WIFI_SUCCESS) { 502 send_resp(dut, conn, SIGMA_ERROR, 503 "NAN subscribe cancel request failed"); 504 } 505 return 0; 506 } 507 } 508 509 if (disc_range) 510 req.rssi_threshold_flag = atoi(disc_range); 511 512 if (sdftx_dw) 513 req.subscribe_count = atoi(sdftx_dw); 514 515 /* Check this once again if config can be called here (TBD) */ 516 if (discrange_ltd) 517 req.rssi_threshold_flag = atoi(discrange_ltd); 518 519 if (include_bit) { 520 int include_bit_val = atoi(include_bit); 521 522 req.serviceResponseInclude = include_bit_val; 523 sigma_dut_print(dut, DUT_MSG_INFO, "Includebit set %d", 524 req.serviceResponseInclude); 525 } 526 527 if (srf_type) { 528 int srf_type_val = atoi(srf_type); 529 530 if (srf_type_val == 1) 531 req.serviceResponseFilter = 0; /* Bloom */ 532 else 533 req.serviceResponseFilter = 1; /* MAC */ 534 req.useServiceResponseFilter = 1; 535 sigma_dut_print(dut, DUT_MSG_INFO, "srfFilter %d", 536 req.serviceResponseFilter); 537 } 538 539 if (mac) { 540 sigma_dut_print(dut, DUT_MSG_INFO, "MAC_ADDR List %s", mac); 541 req.num_intf_addr_present = nan_parse_mac_address_list( 542 dut, mac, &req.intf_addr[0][0], 543 NAN_MAX_SUBSCRIBE_MAX_ADDRESS); 544 } 545 546 memset(input_rx, 0, sizeof(input_rx)); 547 memset(input_tx, 0, sizeof(input_tx)); 548 if (rx_match_filter) { 549 nan_parse_token(rx_match_filter, input_rx, &filter_len_rx); 550 sigma_dut_print(dut, DUT_MSG_INFO, "RxFilterLen %d", 551 filter_len_rx); 552 } 553 if (tx_match_filter) { 554 nan_parse_token(tx_match_filter, input_tx, &filter_len_tx); 555 sigma_dut_print(dut, DUT_MSG_INFO, "TxFilterLen %d", 556 filter_len_tx); 557 } 558 559 if (tx_match_filter) { 560 req.tx_match_filter_len = filter_len_tx; 561 memcpy(req.tx_match_filter, input_tx, filter_len_tx); 562 nan_hex_dump(dut, req.tx_match_filter, filter_len_tx); 563 } 564 if (rx_match_filter) { 565 req.rx_match_filter_len = filter_len_rx; 566 memcpy(req.rx_match_filter, input_rx, filter_len_rx); 567 nan_hex_dump(dut, req.rx_match_filter, filter_len_rx); 568 } 569 570 if (service_name) { 571 strlcpy((char *) req.service_name, service_name, 572 strlen(service_name) + 1); 573 req.service_name_len = strlen(service_name); 574 } 575 576 if (awake_dw_interval) { 577 int input_dw_interval_val = atoi(awake_dw_interval); 578 int awake_dw_int = 0; 579 580 if (input_dw_interval_val > NAN_MAX_ALLOWED_DW_AWAKE_INTERVAL) { 581 sigma_dut_print(dut, DUT_MSG_INFO, 582 "%s: input active dw interval = %d overwritting dw interval to Max allowed dw interval 16", 583 __func__, input_dw_interval_val); 584 input_dw_interval_val = 585 NAN_MAX_ALLOWED_DW_AWAKE_INTERVAL; 586 } 587 sigma_dut_print(dut, DUT_MSG_INFO, 588 "%s: input active DW interval = %d", 589 __func__, input_dw_interval_val); 590 /* 591 * Indicates the interval for Sync beacons and SDF's in 2.4 GHz 592 * or 5 GHz band. Valid values of DW Interval are: 1, 2, 3, 4, 593 * and 5; 0 is reserved. The SDF includes in OTA when enabled. 594 * The publish/subscribe period values don't override the device 595 * level configurations. 596 * input_dw_interval_val is provided by the user are in the 597 * format 2^n-1 = 1/2/4/8/16. Internal implementation expects n 598 * to be passed to indicate the awake_dw_interval. 599 */ 600 if (input_dw_interval_val == 1 || 601 input_dw_interval_val % 2 == 0) { 602 while (input_dw_interval_val > 0) { 603 input_dw_interval_val >>= 1; 604 awake_dw_int++; 605 } 606 } 607 sigma_dut_print(dut, DUT_MSG_INFO, 608 "%s:converted active DW interval = %d", 609 __func__, awake_dw_int); 610 config_req.config_dw.config_2dot4g_dw_band = 1; 611 config_req.config_dw.dw_2dot4g_interval_val = awake_dw_int; 612 config_req.config_dw.config_5g_dw_band = 1; 613 config_req.config_dw.dw_5g_interval_val = awake_dw_int; 614 ret = nan_config_request(0, global_interface_handle, 615 &config_req); 616 if (ret != WIFI_SUCCESS) { 617 sigma_dut_print(dut, DUT_MSG_ERROR, 618 "%s:NAN config request failed", 619 __func__); 620 return -2; 621 } 622 } 623 624 ret = nan_subscribe_request(0, global_interface_handle, &req); 625 if (ret != WIFI_SUCCESS) { 626 send_resp(dut, conn, SIGMA_ERROR, 627 "NAN subscribe request failed"); 628 } 629 630 return 0; 631 } 632 633 634 static int sigma_ndp_configure_band(struct sigma_dut *dut, 635 struct sigma_conn *conn, 636 struct sigma_cmd *cmd, 637 NdpSupportedBand band_config_val) 638 { 639 wifi_error ret; 640 NanDebugParams cfg_debug; 641 int size; 642 643 memset(&cfg_debug, 0, sizeof(NanDebugParams)); 644 cfg_debug.cmd = NAN_TEST_MODE_CMD_NAN_SUPPORTED_BANDS; 645 memcpy(cfg_debug.debug_cmd_data, &band_config_val, sizeof(int)); 646 sigma_dut_print(dut, DUT_MSG_INFO, "%s:setting debug cmd=0x%x", 647 __func__, cfg_debug.cmd); 648 size = sizeof(u32) + sizeof(int); 649 ret = nan_debug_command_config(0, global_interface_handle, cfg_debug, 650 size); 651 if (ret != WIFI_SUCCESS) 652 send_resp(dut, conn, SIGMA_ERROR, "Nan config request failed"); 653 654 return 0; 655 } 656 657 658 static int sigma_nan_data_request(struct sigma_dut *dut, 659 struct sigma_conn *conn, 660 struct sigma_cmd *cmd) 661 { 662 const char *ndp_security = get_param(cmd, "DataPathSecurity"); 663 const char *ndp_resp_mac = get_param(cmd, "RespNanMac"); 664 const char *include_immutable = get_param(cmd, "includeimmutable"); 665 const char *avoid_channel = get_param(cmd, "avoidchannel"); 666 const char *invalid_nan_schedule = get_param(cmd, "InvalidNANSchedule"); 667 const char *map_order = get_param(cmd, "maporder"); 668 #if NAN_CERT_VERSION >= 3 669 const char *qos_config = get_param(cmd, "QoS"); 670 #endif 671 wifi_error ret; 672 NanDataPathInitiatorRequest init_req; 673 NanDebugParams cfg_debug; 674 int size; 675 676 memset(&init_req, 0, sizeof(NanDataPathInitiatorRequest)); 677 678 if (ndp_security) { 679 if (strcasecmp(ndp_security, "open") == 0) 680 init_req.ndp_cfg.security_cfg = 681 NAN_DP_CONFIG_NO_SECURITY; 682 else if (strcasecmp(ndp_security, "secure") == 0) 683 init_req.ndp_cfg.security_cfg = NAN_DP_CONFIG_SECURITY; 684 } 685 686 if (include_immutable) { 687 int include_immutable_val = 0; 688 689 memset(&cfg_debug, 0, sizeof(NanDebugParams)); 690 cfg_debug.cmd = NAN_TEST_MODE_CMD_NDP_INCLUDE_IMMUTABLE; 691 include_immutable_val = atoi(include_immutable); 692 memcpy(cfg_debug.debug_cmd_data, &include_immutable_val, 693 sizeof(int)); 694 size = sizeof(u32) + sizeof(int); 695 nan_debug_command_config(0, global_interface_handle, 696 cfg_debug, size); 697 } 698 699 if (avoid_channel) { 700 int avoid_channel_freq = 0; 701 702 memset(&cfg_debug, 0, sizeof(NanDebugParams)); 703 avoid_channel_freq = channel_to_freq(atoi(avoid_channel)); 704 cfg_debug.cmd = NAN_TEST_MODE_CMD_NDP_AVOID_CHANNEL; 705 memcpy(cfg_debug.debug_cmd_data, &avoid_channel_freq, 706 sizeof(int)); 707 size = sizeof(u32) + sizeof(int); 708 nan_debug_command_config(0, global_interface_handle, 709 cfg_debug, size); 710 } 711 712 if (invalid_nan_schedule) { 713 int invalid_nan_schedule_type = 0; 714 715 memset(&cfg_debug, 0, sizeof(NanDebugParams)); 716 invalid_nan_schedule_type = atoi(invalid_nan_schedule); 717 cfg_debug.cmd = NAN_TEST_MODE_CMD_NAN_SCHED_TYPE; 718 memcpy(cfg_debug.debug_cmd_data, 719 &invalid_nan_schedule_type, sizeof(int)); 720 size = sizeof(u32) + sizeof(int); 721 sigma_dut_print(dut, DUT_MSG_INFO, 722 "%s: invalid schedule type: cmd type = %d and command data = %d", 723 __func__, cfg_debug.cmd, 724 invalid_nan_schedule_type); 725 nan_debug_command_config(0, global_interface_handle, 726 cfg_debug, size); 727 } 728 729 if (map_order) { 730 int map_order_val = 0; 731 732 memset(&cfg_debug, 0, sizeof(NanDebugParams)); 733 cfg_debug.cmd = NAN_TEST_MODE_CMD_NAN_AVAILABILITY_MAP_ORDER; 734 map_order_val = atoi(map_order); 735 memcpy(cfg_debug.debug_cmd_data, &map_order_val, sizeof(int)); 736 size = sizeof(u32) + sizeof(int); 737 sigma_dut_print(dut, DUT_MSG_INFO, 738 "%s: map order: cmd type = %d and command data = %d", 739 __func__, 740 cfg_debug.cmd, map_order_val); 741 nan_debug_command_config(0, global_interface_handle, 742 cfg_debug, size); 743 } 744 745 #if NAN_CERT_VERSION >= 3 746 if (qos_config) { 747 u32 qos_config_val = 0; 748 749 memset(&cfg_debug, 0, sizeof(NanDebugParams)); 750 cfg_debug.cmd = NAN_TEST_MODE_CMD_CONFIG_QOS; 751 qos_config_val = atoi(qos_config); 752 memcpy(cfg_debug.debug_cmd_data, &qos_config_val, sizeof(u32)); 753 size = sizeof(u32) + sizeof(u32); 754 sigma_dut_print(dut, DUT_MSG_INFO, 755 "%s: qos config: cmd type = %d and command data = %d", 756 __func__, cfg_debug.cmd, qos_config_val); 757 nan_debug_command_config(0, global_interface_handle, 758 cfg_debug, size); 759 } 760 #endif 761 762 /* 763 * Setting this flag, so that interface for ping6 command 764 * is set appropriately in traffic_send_ping(). 765 */ 766 dut->ndp_enable = 1; 767 768 /* 769 * Intended sleep after NAN data interface create 770 * before the NAN data request 771 */ 772 sleep(4); 773 774 init_req.requestor_instance_id = global_match_handle; 775 strlcpy((char *) init_req.ndp_iface, "nan0", 776 sizeof(init_req.ndp_iface)); 777 778 if (ndp_resp_mac) { 779 nan_parse_mac_address(dut, ndp_resp_mac, 780 init_req.peer_disc_mac_addr); 781 sigma_dut_print( 782 dut, DUT_MSG_INFO, "PEER MAC ADDR: " MAC_ADDR_STR, 783 MAC_ADDR_ARRAY(init_req.peer_disc_mac_addr)); 784 } else { 785 memcpy(init_req.peer_disc_mac_addr, global_peer_mac_addr, 786 sizeof(init_req.peer_disc_mac_addr)); 787 } 788 789 /* Not requesting the channel and letting FW decide */ 790 if (dut->sta_channel == 0) { 791 init_req.channel_request_type = NAN_DP_CHANNEL_NOT_REQUESTED; 792 init_req.channel = 0; 793 } else { 794 init_req.channel_request_type = NAN_DP_FORCE_CHANNEL_SETUP; 795 init_req.channel = channel_to_freq(dut->sta_channel); 796 } 797 sigma_dut_print(dut, DUT_MSG_INFO, 798 "%s: Initiator Request: Channel = %d Channel Request Type = %d", 799 __func__, init_req.channel, 800 init_req.channel_request_type); 801 802 if (dut->nan_pmk_len == NAN_PMK_INFO_LEN) { 803 init_req.key_info.key_type = NAN_SECURITY_KEY_INPUT_PMK; 804 memcpy(&init_req.key_info.body.pmk_info.pmk[0], 805 &dut->nan_pmk[0], NAN_PMK_INFO_LEN); 806 init_req.key_info.body.pmk_info.pmk_len = NAN_PMK_INFO_LEN; 807 sigma_dut_print(dut, DUT_MSG_INFO, "%s: pmk len = %d", 808 __func__, 809 init_req.key_info.body.pmk_info.pmk_len); 810 } 811 812 ret = nan_data_request_initiator(0, global_interface_handle, &init_req); 813 if (ret != WIFI_SUCCESS) { 814 send_resp(dut, conn, SIGMA_ERROR, 815 "Unable to initiate nan data request"); 816 return 0; 817 } 818 819 return 0; 820 } 821 822 823 static int sigma_nan_data_response(struct sigma_dut *dut, 824 struct sigma_conn *conn, 825 struct sigma_cmd *cmd) 826 { 827 const char *ndl_response = get_param(cmd, "NDLresponse"); 828 const char *m4_response_type = get_param(cmd, "M4ResponseType"); 829 wifi_error ret; 830 NanDebugParams cfg_debug; 831 int size; 832 833 if (ndl_response) { 834 int auto_responder_mode_val = 0; 835 836 sigma_dut_print(dut, DUT_MSG_INFO, 837 "%s: ndl_response = (%s) is passed", 838 __func__, ndl_response); 839 memset(&cfg_debug, 0, sizeof(NanDebugParams)); 840 cfg_debug.cmd = NAN_TEST_MODE_CMD_AUTO_RESPONDER_MODE; 841 if (strcasecmp(ndl_response, "Auto") == 0) { 842 auto_responder_mode_val = NAN_DATA_RESPONDER_MODE_AUTO; 843 } else if (strcasecmp(ndl_response, "Reject") == 0) { 844 auto_responder_mode_val = 845 NAN_DATA_RESPONDER_MODE_REJECT; 846 } else if (strcasecmp(ndl_response, "Accept") == 0) { 847 auto_responder_mode_val = 848 NAN_DATA_RESPONDER_MODE_ACCEPT; 849 } else if (strcasecmp(ndl_response, "Counter") == 0) { 850 auto_responder_mode_val = 851 NAN_DATA_RESPONDER_MODE_COUNTER; 852 } else { 853 sigma_dut_print(dut, DUT_MSG_ERROR, 854 "%s: Invalid ndl_response", 855 __func__); 856 return 0; 857 } 858 memcpy(cfg_debug.debug_cmd_data, &auto_responder_mode_val, 859 sizeof(int)); 860 size = sizeof(u32) + sizeof(int); 861 ret = nan_debug_command_config(0, global_interface_handle, 862 cfg_debug, size); 863 if (ret != WIFI_SUCCESS) { 864 send_resp(dut, conn, SIGMA_ERROR, 865 "Nan config request failed"); 866 } 867 } 868 869 if (m4_response_type) { 870 int m4_response_type_val = 0; 871 872 sigma_dut_print(dut, DUT_MSG_INFO, 873 "%s: m4_response_type = (%s) is passed", 874 __func__, m4_response_type); 875 memset(&cfg_debug, 0, sizeof(NanDebugParams)); 876 cfg_debug.cmd = NAN_TEST_MODE_CMD_M4_RESPONSE_TYPE; 877 if (strcasecmp(m4_response_type, "Accept") == 0) 878 m4_response_type_val = NAN_DATA_PATH_M4_RESPONSE_ACCEPT; 879 else if (strcasecmp(m4_response_type, "Reject") == 0) 880 m4_response_type_val = NAN_DATA_PATH_M4_RESPONSE_REJECT; 881 else if (strcasecmp(m4_response_type, "BadMic") == 0) 882 m4_response_type_val = NAN_DATA_PATH_M4_RESPONSE_BADMIC; 883 884 memcpy(cfg_debug.debug_cmd_data, &m4_response_type_val, 885 sizeof(int)); 886 size = sizeof(u32) + sizeof(int); 887 ret = nan_debug_command_config(0, global_interface_handle, 888 cfg_debug, size); 889 if (ret != WIFI_SUCCESS) { 890 send_resp(dut, conn, SIGMA_ERROR, 891 "Nan config request failed"); 892 } 893 } 894 895 return 0; 896 } 897 898 899 static int sigma_nan_data_end(struct sigma_dut *dut, struct sigma_cmd *cmd) 900 { 901 const char *nmf_security_config = get_param(cmd, "Security"); 902 NanDataPathEndRequest req; 903 NanDebugParams cfg_debug; 904 int size; 905 906 memset(&req, 0, sizeof(NanDataPathEndRequest)); 907 memset(&cfg_debug, 0, sizeof(NanDebugParams)); 908 if (nmf_security_config) { 909 int nmf_security_config_val = 0; 910 911 cfg_debug.cmd = NAN_TEST_MODE_CMD_NAN_NMF_CLEAR_CONFIG; 912 if (strcasecmp(nmf_security_config, "open") == 0) 913 nmf_security_config_val = NAN_NMF_CLEAR_ENABLE; 914 else if (strcasecmp(nmf_security_config, "secure") == 0) 915 nmf_security_config_val = NAN_NMF_CLEAR_DISABLE; 916 memcpy(cfg_debug.debug_cmd_data, 917 &nmf_security_config_val, sizeof(int)); 918 size = sizeof(u32) + sizeof(int); 919 sigma_dut_print(dut, DUT_MSG_INFO, 920 "%s: nmf_security_config_val -- cmd type = %d and command data = %d", 921 __func__, cfg_debug.cmd, 922 nmf_security_config_val); 923 nan_debug_command_config(0, global_interface_handle, 924 cfg_debug, size); 925 } 926 927 req.num_ndp_instances = 1; 928 req.ndp_instance_id[0] = global_ndp_instance_id; 929 930 nan_data_end(0, global_interface_handle, &req); 931 return 0; 932 } 933 934 935 static int sigma_nan_range_request(struct sigma_dut *dut, 936 struct sigma_cmd *cmd) 937 { 938 const char *dest_mac = get_param(cmd, "destmac"); 939 NanSubscribeRequest req; 940 941 memset(&req, 0, sizeof(NanSubscribeRequest)); 942 req.period = 1; 943 req.subscribe_type = NAN_SUBSCRIBE_TYPE_ACTIVE; 944 req.serviceResponseFilter = NAN_SRF_ATTR_BLOOM_FILTER; 945 req.serviceResponseInclude = NAN_SRF_INCLUDE_RESPOND; 946 req.ssiRequiredForMatchIndication = NAN_SSI_NOT_REQUIRED_IN_MATCH_IND; 947 req.subscribe_match_indicator = NAN_MATCH_ALG_MATCH_CONTINUOUS; 948 req.subscribe_count = 0; 949 strlcpy((char *) req.service_name, DEFAULT_SVC, 950 NAN_MAX_SERVICE_NAME_LEN); 951 req.service_name_len = strlen((char *) req.service_name); 952 953 req.subscribe_id = global_subscribe_id; 954 req.sdea_params.ranging_state = 1; 955 req.sdea_params.range_report = NAN_ENABLE_RANGE_REPORT; 956 req.range_response_cfg.requestor_instance_id = global_match_handle; 957 req.range_response_cfg.ranging_response = NAN_RANGE_REQUEST_ACCEPT; 958 req.ranging_cfg.config_ranging_indications = 959 NAN_RANGING_INDICATE_CONTINUOUS_MASK; 960 if (dest_mac) { 961 nan_parse_mac_address(dut, dest_mac, 962 req.range_response_cfg.peer_addr); 963 sigma_dut_print( 964 dut, DUT_MSG_INFO, "peer mac addr: " MAC_ADDR_STR, 965 MAC_ADDR_ARRAY(req.range_response_cfg.peer_addr)); 966 } 967 nan_subscribe_request(0, global_interface_handle, &req); 968 969 return 0; 970 } 971 972 973 static int sigma_nan_cancel_range(struct sigma_dut *dut, 974 struct sigma_cmd *cmd) 975 { 976 const char *dest_mac = get_param(cmd, "destmac"); 977 NanPublishRequest req; 978 979 memset(&req, 0, sizeof(NanPublishRequest)); 980 req.ttl = 0; 981 req.period = 1; 982 req.publish_match_indicator = 1; 983 req.publish_type = NAN_PUBLISH_TYPE_UNSOLICITED; 984 req.tx_type = NAN_TX_TYPE_BROADCAST; 985 req.publish_count = 0; 986 strlcpy((char *) req.service_name, DEFAULT_SVC, 987 NAN_MAX_SERVICE_NAME_LEN); 988 req.service_name_len = strlen((char *) req.service_name); 989 req.publish_id = global_publish_id; 990 req.range_response_cfg.ranging_response = NAN_RANGE_REQUEST_CANCEL; 991 if (dest_mac) { 992 nan_parse_mac_address(dut, dest_mac, 993 req.range_response_cfg.peer_addr); 994 sigma_dut_print( 995 dut, DUT_MSG_INFO, "peer mac addr: " MAC_ADDR_STR, 996 MAC_ADDR_ARRAY(req.range_response_cfg.peer_addr)); 997 } 998 nan_publish_request(0, global_interface_handle, &req); 999 1000 return 0; 1001 } 1002 1003 1004 static int sigma_nan_schedule_update(struct sigma_dut *dut, 1005 struct sigma_cmd *cmd) 1006 { 1007 const char *schedule_update_type = get_param(cmd, "type"); 1008 const char *channel_availability = get_param(cmd, 1009 "ChannelAvailability"); 1010 const char *responder_nmi_mac = get_param(cmd, "ResponderNMI"); 1011 NanDebugParams cfg_debug; 1012 int size = 0; 1013 1014 memset(&cfg_debug, 0, sizeof(NanDebugParams)); 1015 1016 if (!schedule_update_type) 1017 return 0; 1018 1019 if (strcasecmp(schedule_update_type, "ULWnotify") == 0) { 1020 cfg_debug.cmd = NAN_TEST_MODE_CMD_NAN_SCHED_UPDATE_ULW_NOTIFY; 1021 size = sizeof(u32); 1022 sigma_dut_print(dut, DUT_MSG_INFO, 1023 "%s: Schedule Update cmd type = %d", __func__, 1024 cfg_debug.cmd); 1025 if (channel_availability) { 1026 int channel_availability_val; 1027 1028 channel_availability_val = atoi(channel_availability); 1029 size += sizeof(int); 1030 memcpy(cfg_debug.debug_cmd_data, 1031 &channel_availability_val, sizeof(int)); 1032 sigma_dut_print(dut, DUT_MSG_INFO, 1033 "%s: Schedule Update cmd data = %d size = %d", 1034 __func__, channel_availability_val, 1035 size); 1036 } 1037 } else if (strcasecmp(schedule_update_type, "NDLnegotiate") == 0) { 1038 cfg_debug.cmd = 1039 NAN_TEST_MODE_CMD_NAN_SCHED_UPDATE_NDL_NEGOTIATE; 1040 size = sizeof(u32); 1041 sigma_dut_print(dut, DUT_MSG_INFO, 1042 "%s: Schedule Update cmd type = %d", __func__, 1043 cfg_debug.cmd); 1044 if (responder_nmi_mac) { 1045 u8 responder_nmi_mac_addr[NAN_MAC_ADDR_LEN]; 1046 1047 nan_parse_mac_address(dut, responder_nmi_mac, 1048 responder_nmi_mac_addr); 1049 size += NAN_MAC_ADDR_LEN; 1050 memcpy(cfg_debug.debug_cmd_data, responder_nmi_mac_addr, 1051 NAN_MAC_ADDR_LEN); 1052 sigma_dut_print(dut, DUT_MSG_INFO, 1053 "%s: RESPONDER NMI MAC: "MAC_ADDR_STR, 1054 __func__, 1055 MAC_ADDR_ARRAY(responder_nmi_mac_addr)); 1056 sigma_dut_print(dut, DUT_MSG_INFO, 1057 "%s: Schedule Update: cmd size = %d", 1058 __func__, size); 1059 } 1060 } else if (strcasecmp(schedule_update_type, "NDLnotify") == 0) { 1061 cfg_debug.cmd = NAN_TEST_MODE_CMD_NAN_SCHED_UPDATE_NDL_NOTIFY; 1062 size = sizeof(u32); 1063 sigma_dut_print(dut, DUT_MSG_INFO, 1064 "%s: Schedule Update cmd type = %d", __func__, 1065 cfg_debug.cmd); 1066 } 1067 1068 nan_debug_command_config(0, global_interface_handle, cfg_debug, size); 1069 1070 return 0; 1071 } 1072 1073 1074 int config_post_disc_attr(void) 1075 { 1076 wifi_error ret; 1077 NanConfigRequest configReq; 1078 1079 memset(&configReq, 0, sizeof(NanConfigRequest)); 1080 1081 /* Configure Post disc attr */ 1082 /* Make these defines and use correct enum */ 1083 configReq.num_config_discovery_attr = 1; 1084 configReq.discovery_attr_val[0].type = 4; /* Further Nan discovery */ 1085 configReq.discovery_attr_val[0].role = 0; 1086 configReq.discovery_attr_val[0].transmit_freq = 1; 1087 configReq.discovery_attr_val[0].duration = 0; 1088 configReq.discovery_attr_val[0].avail_interval_bitmap = 0x00000008; 1089 1090 ret = nan_config_request(0, global_interface_handle, &configReq); 1091 if (ret != WIFI_SUCCESS) { 1092 sigma_dut_print(global_dut, DUT_MSG_INFO, 1093 "NAN config request failed while configuring post discovery attribute"); 1094 } 1095 1096 return 0; 1097 } 1098 1099 1100 int sigma_nan_publish_request(struct sigma_dut *dut, struct sigma_conn *conn, 1101 struct sigma_cmd *cmd) 1102 { 1103 const char *publish_type = get_param(cmd, "PublishType"); 1104 const char *service_name = get_param(cmd, "ServiceName"); 1105 const char *disc_range = get_param(cmd, "DiscoveryRange"); 1106 const char *rx_match_filter = get_param(cmd, "rxMatchFilter"); 1107 const char *tx_match_filter = get_param(cmd, "txMatchFilter"); 1108 const char *sdftx_dw = get_param(cmd, "SDFTxDW"); 1109 const char *discrange_ltd = get_param(cmd, "DiscRangeLtd"); 1110 const char *ndp_enable = get_param(cmd, "DataPathFlag"); 1111 const char *ndp_type = get_param(cmd, "DataPathType"); 1112 const char *data_path_security = get_param(cmd, "datapathsecurity"); 1113 const char *range_required = get_param(cmd, "rangerequired"); 1114 const char *awake_dw_interval = get_param(cmd, "awakeDWint"); 1115 #if NAN_CERT_VERSION >= 3 1116 const char *qos_config = get_param(cmd, "QoS"); 1117 #endif 1118 NanPublishRequest req; 1119 NanConfigRequest config_req; 1120 int filter_len_rx = 0, filter_len_tx = 0; 1121 u8 input_rx[NAN_MAX_MATCH_FILTER_LEN]; 1122 u8 input_tx[NAN_MAX_MATCH_FILTER_LEN]; 1123 wifi_error ret; 1124 1125 memset(&req, 0, sizeof(NanPublishRequest)); 1126 memset(&config_req, 0, sizeof(NanConfigRequest)); 1127 req.ttl = 0; 1128 req.period = 1; 1129 req.publish_match_indicator = 1; 1130 req.publish_type = NAN_PUBLISH_TYPE_UNSOLICITED; 1131 req.tx_type = NAN_TX_TYPE_BROADCAST; 1132 req.publish_count = 0; 1133 req.service_responder_policy = NAN_SERVICE_ACCEPT_POLICY_ALL; 1134 1135 if (global_publish_service_name_len && 1136 service_name && 1137 strcasecmp((char *) global_publish_service_name, 1138 service_name) == 0 && 1139 global_publish_id) { 1140 req.publish_id = global_publish_id; 1141 sigma_dut_print(dut, DUT_MSG_INFO, 1142 "%s: updating publish_id = %d in publish request", 1143 __func__, req.publish_id); 1144 } 1145 1146 if (service_name) { 1147 strlcpy((char *) req.service_name, service_name, 1148 sizeof(req.service_name)); 1149 req.service_name_len = strlen((char *) req.service_name); 1150 strlcpy((char *) global_publish_service_name, service_name, 1151 sizeof(global_publish_service_name)); 1152 global_publish_service_name_len = 1153 strlen((char *) global_publish_service_name); 1154 } 1155 1156 if (publish_type) { 1157 if (strcasecmp(publish_type, "Solicited") == 0) { 1158 req.publish_type = NAN_PUBLISH_TYPE_SOLICITED; 1159 } else if (strcasecmp(publish_type, "Unsolicited") == 0) { 1160 req.publish_type = NAN_PUBLISH_TYPE_UNSOLICITED; 1161 } else if (strcasecmp(publish_type, "Cancel") == 0) { 1162 NanPublishCancelRequest req; 1163 1164 memset(&req, 0, sizeof(NanPublishCancelRequest)); 1165 ret = nan_publish_cancel_request( 1166 0, global_interface_handle, &req); 1167 if (ret != WIFI_SUCCESS) { 1168 send_resp(dut, conn, SIGMA_ERROR, 1169 "Unable to cancel nan publish request"); 1170 } 1171 return 0; 1172 } 1173 } 1174 1175 if (disc_range) 1176 req.rssi_threshold_flag = atoi(disc_range); 1177 1178 if (sdftx_dw) 1179 req.publish_count = atoi(sdftx_dw); 1180 1181 if (discrange_ltd) 1182 req.rssi_threshold_flag = atoi(discrange_ltd); 1183 1184 memset(input_rx, 0, sizeof(input_rx)); 1185 memset(input_tx, 0, sizeof(input_tx)); 1186 if (rx_match_filter) { 1187 nan_parse_token(rx_match_filter, input_rx, &filter_len_rx); 1188 sigma_dut_print(dut, DUT_MSG_INFO, "RxFilterLen %d", 1189 filter_len_rx); 1190 } 1191 if (tx_match_filter) { 1192 nan_parse_token(tx_match_filter, input_tx, &filter_len_tx); 1193 sigma_dut_print(dut, DUT_MSG_INFO, "TxFilterLen %d", 1194 filter_len_tx); 1195 } 1196 1197 if (is_fam == 1) { 1198 config_post_disc_attr(); 1199 /* 1200 * 8-bit bitmap which allows the Host to associate this publish 1201 * with a particular Post-NAN Connectivity attribute which has 1202 * been sent down in a NanConfigureRequest/NanEnableRequest 1203 * message. If the DE fails to find a configured Post-NAN 1204 * connectivity attributes referenced by the bitmap, the DE will 1205 * return an error code to the Host. If the Publish is 1206 * configured to use a Post-NAN Connectivity attribute and the 1207 * Host does not refresh the Post-NAN Connectivity attribute the 1208 * Publish will be canceled and the Host will be sent a 1209 * PublishTerminatedIndication message. 1210 */ 1211 req.connmap = 0x10; 1212 } 1213 1214 if (tx_match_filter) { 1215 req.tx_match_filter_len = filter_len_tx; 1216 memcpy(req.tx_match_filter, input_tx, filter_len_tx); 1217 nan_hex_dump(dut, req.tx_match_filter, filter_len_tx); 1218 } 1219 1220 if (rx_match_filter) { 1221 req.rx_match_filter_len = filter_len_rx; 1222 memcpy(req.rx_match_filter, input_rx, filter_len_rx); 1223 nan_hex_dump(dut, req.rx_match_filter, filter_len_rx); 1224 } 1225 1226 if (service_name) { 1227 strlcpy((char *) req.service_name, service_name, 1228 strlen(service_name) + 1); 1229 req.service_name_len = strlen(service_name); 1230 } 1231 1232 if (ndp_enable) { 1233 if (strcasecmp(ndp_enable, "enable") == 0) 1234 req.sdea_params.config_nan_data_path = 1; 1235 else 1236 req.sdea_params.config_nan_data_path = 0; 1237 1238 if (ndp_type) 1239 req.sdea_params.ndp_type = atoi(ndp_type); 1240 1241 if (data_path_security) { 1242 if (strcasecmp(data_path_security, "secure") == 0) { 1243 req.sdea_params.security_cfg = 1244 NAN_DP_CONFIG_SECURITY; 1245 } else if (strcasecmp(data_path_security, "open") == 1246 0) { 1247 req.sdea_params.security_cfg = 1248 NAN_DP_CONFIG_NO_SECURITY; 1249 } 1250 } 1251 1252 if (dut->nan_pmk_len == NAN_PMK_INFO_LEN) { 1253 req.key_info.key_type = NAN_SECURITY_KEY_INPUT_PMK; 1254 memcpy(&req.key_info.body.pmk_info.pmk[0], 1255 &dut->nan_pmk[0], NAN_PMK_INFO_LEN); 1256 req.key_info.body.pmk_info.pmk_len = NAN_PMK_INFO_LEN; 1257 sigma_dut_print(dut, DUT_MSG_INFO, "%s: pmk len = %d", 1258 __func__, req.key_info.body.pmk_info.pmk_len); 1259 } 1260 } 1261 if (range_required && strcasecmp(range_required, "enable") == 0) { 1262 req.sdea_params.ranging_state = NAN_RANGING_ENABLE; 1263 req.sdea_params.range_report = NAN_ENABLE_RANGE_REPORT; 1264 } 1265 1266 if (awake_dw_interval) { 1267 int input_dw_interval_val = atoi(awake_dw_interval); 1268 int awake_dw_int = 0; 1269 1270 if (input_dw_interval_val > NAN_MAX_ALLOWED_DW_AWAKE_INTERVAL) { 1271 sigma_dut_print(dut, DUT_MSG_INFO, 1272 "%s: input active dw interval = %d overwritting dw interval to Max allowed dw interval 16", 1273 __func__, input_dw_interval_val); 1274 input_dw_interval_val = 1275 NAN_MAX_ALLOWED_DW_AWAKE_INTERVAL; 1276 } 1277 sigma_dut_print(dut, DUT_MSG_INFO, 1278 "%s: input active DW interval = %d", 1279 __func__, input_dw_interval_val); 1280 /* 1281 * Indicates the interval for Sync beacons and SDF's in 2.4 GHz 1282 * or 5 GHz band. Valid values of DW Interval are: 1, 2, 3, 4, 1283 * and 5; 0 is reserved. The SDF includes in OTA when enabled. 1284 * The publish/subscribe period. values don't override the 1285 * device level configurations. 1286 * input_dw_interval_val is provided by the user are in the 1287 * format 2^n-1 = 1/2/4/8/16. Internal implementation expects n 1288 * to be passed to indicate the awake_dw_interval. 1289 */ 1290 if (input_dw_interval_val == 1 || 1291 input_dw_interval_val % 2 == 0) { 1292 while (input_dw_interval_val > 0) { 1293 input_dw_interval_val >>= 1; 1294 awake_dw_int++; 1295 } 1296 } 1297 sigma_dut_print(dut, DUT_MSG_INFO, 1298 "%s:converted active DW interval = %d", 1299 __func__, awake_dw_int); 1300 config_req.config_dw.config_2dot4g_dw_band = 1; 1301 config_req.config_dw.dw_2dot4g_interval_val = awake_dw_int; 1302 config_req.config_dw.config_5g_dw_band = 1; 1303 config_req.config_dw.dw_5g_interval_val = awake_dw_int; 1304 ret = nan_config_request(0, global_interface_handle, 1305 &config_req); 1306 if (ret != WIFI_SUCCESS) { 1307 sigma_dut_print(dut, DUT_MSG_ERROR, 1308 "%s:NAN config request failed", 1309 __func__); 1310 return -2; 1311 } 1312 } 1313 1314 #if NAN_CERT_VERSION >= 3 1315 if (qos_config) 1316 req.sdea_params.qos_cfg = (NanQosCfgStatus) atoi(qos_config); 1317 #endif 1318 1319 ret = nan_publish_request(0, global_interface_handle, &req); 1320 if (ret != WIFI_SUCCESS) 1321 send_resp(dut, conn, SIGMA_ERROR, "Unable to publish"); 1322 1323 if (ndp_enable) 1324 dut->ndp_enable = 1; 1325 1326 return 0; 1327 } 1328 1329 1330 static int nan_further_availability_rx(struct sigma_dut *dut, 1331 struct sigma_conn *conn, 1332 struct sigma_cmd *cmd) 1333 { 1334 const char *master_pref = get_param(cmd, "MasterPref"); 1335 const char *rand_fac = get_param(cmd, "RandFactor"); 1336 const char *hop_count = get_param(cmd, "HopCount"); 1337 wifi_error ret; 1338 struct timespec abstime; 1339 1340 NanEnableRequest req; 1341 1342 memset(&req, 0, sizeof(NanEnableRequest)); 1343 req.cluster_low = 0; 1344 req.cluster_high = 0xFFFF; 1345 req.master_pref = 30; 1346 1347 if (master_pref) 1348 req.master_pref = strtoul(master_pref, NULL, 0); 1349 1350 if (rand_fac) { 1351 int rand_fac_val = strtoul(rand_fac, NULL, 0); 1352 1353 req.config_random_factor_force = 1; 1354 req.random_factor_force_val = rand_fac_val; 1355 } 1356 1357 if (hop_count) { 1358 int hop_count_val = strtoul(hop_count, NULL, 0); 1359 1360 req.config_hop_count_force = 1; 1361 req.hop_count_force_val = hop_count_val; 1362 } 1363 1364 ret = nan_enable_request(0, global_interface_handle, &req); 1365 if (ret != WIFI_SUCCESS) { 1366 send_resp(dut, conn, SIGMA_ERROR, "Unable to enable nan"); 1367 return 0; 1368 } 1369 1370 abstime.tv_sec = 4; 1371 abstime.tv_nsec = 0; 1372 wait(abstime); 1373 1374 return 0; 1375 } 1376 1377 1378 static int nan_further_availability_tx(struct sigma_dut *dut, 1379 struct sigma_conn *conn, 1380 struct sigma_cmd *cmd) 1381 { 1382 const char *master_pref = get_param(cmd, "MasterPref"); 1383 const char *rand_fac = get_param(cmd, "RandFactor"); 1384 const char *hop_count = get_param(cmd, "HopCount"); 1385 wifi_error ret; 1386 1387 NanEnableRequest req; 1388 NanConfigRequest configReq; 1389 1390 memset(&req, 0, sizeof(NanEnableRequest)); 1391 req.cluster_low = 0; 1392 req.cluster_high = 0xFFFF; 1393 req.master_pref = 30; 1394 1395 if (master_pref) 1396 req.master_pref = strtoul(master_pref, NULL, 0); 1397 1398 if (rand_fac) { 1399 int rand_fac_val = strtoul(rand_fac, NULL, 0); 1400 1401 req.config_random_factor_force = 1; 1402 req.random_factor_force_val = rand_fac_val; 1403 } 1404 1405 if (hop_count) { 1406 int hop_count_val = strtoul(hop_count, NULL, 0); 1407 1408 req.config_hop_count_force = 1; 1409 req.hop_count_force_val = hop_count_val; 1410 } 1411 1412 ret = nan_enable_request(0, global_interface_handle, &req); 1413 if (ret != WIFI_SUCCESS) { 1414 send_resp(dut, conn, SIGMA_ERROR, "Unable to enable nan"); 1415 return 0; 1416 } 1417 1418 /* Start the config of fam */ 1419 1420 memset(&configReq, 0, sizeof(NanConfigRequest)); 1421 1422 configReq.config_fam = 1; 1423 configReq.fam_val.numchans = 1; 1424 configReq.fam_val.famchan[0].entry_control = 0; 1425 configReq.fam_val.famchan[0].class_val = 81; 1426 configReq.fam_val.famchan[0].channel = 6; 1427 configReq.fam_val.famchan[0].mapid = 0; 1428 configReq.fam_val.famchan[0].avail_interval_bitmap = 0x7ffffffe; 1429 1430 ret = nan_config_request(0, global_interface_handle, &configReq); 1431 if (ret != WIFI_SUCCESS) 1432 send_resp(dut, conn, SIGMA_ERROR, "Nan config request failed"); 1433 1434 return 0; 1435 } 1436 1437 1438 int sigma_nan_transmit_followup(struct sigma_dut *dut, 1439 struct sigma_conn *conn, 1440 struct sigma_cmd *cmd) 1441 { 1442 const char *mac = get_param(cmd, "mac"); 1443 const char *requestor_id = get_param(cmd, "RemoteInstanceId"); 1444 const char *local_id = get_param(cmd, "LocalInstanceId"); 1445 const char *service_name = get_param(cmd, "servicename"); 1446 wifi_error ret; 1447 NanTransmitFollowupRequest req; 1448 1449 memset(&req, 0, sizeof(NanTransmitFollowupRequest)); 1450 req.requestor_instance_id = global_match_handle; 1451 req.addr[0] = 0xFF; 1452 req.addr[1] = 0xFF; 1453 req.addr[2] = 0xFF; 1454 req.addr[3] = 0xFF; 1455 req.addr[4] = 0xFF; 1456 req.addr[5] = 0xFF; 1457 req.priority = NAN_TX_PRIORITY_NORMAL; 1458 req.dw_or_faw = 0; 1459 1460 if (service_name) 1461 req.service_specific_info_len = strlen(service_name); 1462 1463 if (requestor_id) { 1464 /* int requestor_id_val = atoi(requestor_id); */ 1465 req.requestor_instance_id = global_match_handle; 1466 } 1467 if (local_id) { 1468 /* int local_id_val = atoi(local_id); */ 1469 req.publish_subscribe_id = global_header_handle; 1470 } 1471 1472 if (mac == NULL) { 1473 sigma_dut_print(dut, DUT_MSG_ERROR, "Invalid MAC Address"); 1474 return -1; 1475 } 1476 nan_parse_mac_address(dut, mac, req.addr); 1477 1478 if (requestor_id) 1479 req.requestor_instance_id = strtoul(requestor_id, NULL, 0); 1480 1481 ret = nan_transmit_followup_request(0, global_interface_handle, &req); 1482 if (ret != WIFI_SUCCESS) { 1483 send_resp(dut, conn, SIGMA_ERROR, 1484 "Unable to complete nan transmit followup"); 1485 } 1486 1487 return 0; 1488 } 1489 1490 1491 /* NotifyResponse invoked to notify the status of the Request */ 1492 void nan_notify_response(transaction_id id, NanResponseMsg *rsp_data) 1493 { 1494 sigma_dut_print(global_dut, DUT_MSG_INFO, 1495 "%s: status %d response_type %d", 1496 __func__, rsp_data->status, rsp_data->response_type); 1497 if (rsp_data->response_type == NAN_RESPONSE_STATS && 1498 rsp_data->body.stats_response.stats_type == 1499 NAN_STATS_ID_DE_TIMING_SYNC) { 1500 NanSyncStats *pSyncStats; 1501 1502 sigma_dut_print(global_dut, DUT_MSG_INFO, 1503 "%s: stats_type %d", __func__, 1504 rsp_data->body.stats_response.stats_type); 1505 pSyncStats = &rsp_data->body.stats_response.data.sync_stats; 1506 memcpy(&global_nan_sync_stats, pSyncStats, 1507 sizeof(NanSyncStats)); 1508 pthread_cond_signal(&gCondition); 1509 } else if (rsp_data->response_type == NAN_RESPONSE_PUBLISH) { 1510 sigma_dut_print(global_dut, DUT_MSG_INFO, 1511 "%s: publish_id %d\n", 1512 __func__, 1513 rsp_data->body.publish_response.publish_id); 1514 global_publish_id = rsp_data->body.publish_response.publish_id; 1515 } else if (rsp_data->response_type == NAN_RESPONSE_SUBSCRIBE) { 1516 sigma_dut_print(global_dut, DUT_MSG_INFO, 1517 "%s: subscribe_id %d\n", 1518 __func__, 1519 rsp_data->body.subscribe_response.subscribe_id); 1520 global_subscribe_id = 1521 rsp_data->body.subscribe_response.subscribe_id; 1522 } 1523 } 1524 1525 1526 /* Events Callback */ 1527 void nan_event_publish_replied(NanPublishRepliedInd *event) 1528 { 1529 sigma_dut_print(global_dut, DUT_MSG_INFO, 1530 "%s: handle %d " MAC_ADDR_STR " rssi:%d", 1531 __func__, event->requestor_instance_id, 1532 MAC_ADDR_ARRAY(event->addr), event->rssi_value); 1533 event_anyresponse = 1; 1534 snprintf(global_event_resp_buf, sizeof(global_event_resp_buf), 1535 "EventName,Replied,RemoteInstanceID %d,mac," MAC_ADDR_STR, 1536 (event->requestor_instance_id >> 24), 1537 MAC_ADDR_ARRAY(event->addr)); 1538 } 1539 1540 1541 /* Events Callback */ 1542 void nan_event_publish_terminated(NanPublishTerminatedInd *event) 1543 { 1544 sigma_dut_print(global_dut, DUT_MSG_INFO, "%s: publish_id %d reason %d", 1545 __func__, event->publish_id, event->reason); 1546 } 1547 1548 1549 /* Events Callback */ 1550 void nan_event_match(NanMatchInd *event) 1551 { 1552 sigma_dut_print(global_dut, DUT_MSG_INFO, 1553 "%s: Pub/Sub Id %d remote_requestor_id %08x " 1554 MAC_ADDR_STR 1555 " rssi:%d", 1556 __func__, 1557 event->publish_subscribe_id, 1558 event->requestor_instance_id, 1559 MAC_ADDR_ARRAY(event->addr), 1560 event->rssi_value); 1561 event_anyresponse = 1; 1562 global_header_handle = event->publish_subscribe_id; 1563 global_match_handle = event->requestor_instance_id; 1564 memcpy(global_peer_mac_addr, event->addr, sizeof(global_peer_mac_addr)); 1565 1566 /* memset(event_resp_buf, 0, sizeof(event_resp_buf)); */ 1567 /* global_pub_sub_handle = event->header.handle; */ 1568 /* Print the SSI */ 1569 sigma_dut_print(global_dut, DUT_MSG_INFO, "Printing SSI:"); 1570 nan_hex_dump(global_dut, event->service_specific_info, 1571 event->service_specific_info_len); 1572 snprintf(global_event_resp_buf, sizeof(global_event_resp_buf), 1573 "EventName,DiscoveryResult,RemoteInstanceID,%d,LocalInstanceID,%d,mac," 1574 MAC_ADDR_STR " ", (event->requestor_instance_id >> 24), 1575 event->publish_subscribe_id, MAC_ADDR_ARRAY(event->addr)); 1576 1577 /* Print the match filter */ 1578 sigma_dut_print(global_dut, DUT_MSG_INFO, "Printing sdf match filter:"); 1579 nan_hex_dump(global_dut, event->sdf_match_filter, 1580 event->sdf_match_filter_len); 1581 1582 /* Print the conn_capability */ 1583 sigma_dut_print(global_dut, DUT_MSG_INFO, 1584 "Printing PostConnectivity Capability"); 1585 if (event->is_conn_capability_valid) { 1586 sigma_dut_print(global_dut, DUT_MSG_INFO, "Wfd supported:%s", 1587 event->conn_capability.is_wfd_supported ? 1588 "yes" : "no"); 1589 sigma_dut_print(global_dut, DUT_MSG_INFO, "Wfds supported:%s", 1590 (event->conn_capability.is_wfds_supported ? 1591 "yes" : "no")); 1592 sigma_dut_print(global_dut, DUT_MSG_INFO, "TDLS supported:%s", 1593 (event->conn_capability.is_tdls_supported ? 1594 "yes" : "no")); 1595 sigma_dut_print(global_dut, DUT_MSG_INFO, "IBSS supported:%s", 1596 (event->conn_capability.is_ibss_supported ? 1597 "yes" : "no")); 1598 sigma_dut_print(global_dut, DUT_MSG_INFO, "Mesh supported:%s", 1599 (event->conn_capability.is_mesh_supported ? 1600 "yes" : "no")); 1601 sigma_dut_print(global_dut, DUT_MSG_INFO, "Infra Field:%d", 1602 event->conn_capability.wlan_infra_field); 1603 } else { 1604 sigma_dut_print(global_dut, DUT_MSG_INFO, 1605 "PostConnectivity Capability not present"); 1606 } 1607 1608 /* Print the discovery_attr */ 1609 sigma_dut_print(global_dut, DUT_MSG_INFO, 1610 "Printing PostDiscovery Attribute"); 1611 if (event->num_rx_discovery_attr) { 1612 int idx; 1613 1614 for (idx = 0; idx < event->num_rx_discovery_attr; idx++) { 1615 sigma_dut_print(global_dut, DUT_MSG_INFO, 1616 "PostDiscovery Attribute - %d", idx); 1617 sigma_dut_print(global_dut, DUT_MSG_INFO, 1618 "Conn Type:%d Device Role:%d" 1619 MAC_ADDR_STR, 1620 event->discovery_attr[idx].type, 1621 event->discovery_attr[idx].role, 1622 MAC_ADDR_ARRAY(event->discovery_attr[idx].addr)); 1623 sigma_dut_print(global_dut, DUT_MSG_INFO, 1624 "Duration:%d MapId:%d " 1625 "avail_interval_bitmap:%04x", 1626 event->discovery_attr[idx].duration, 1627 event->discovery_attr[idx].mapid, 1628 event->discovery_attr[idx].avail_interval_bitmap); 1629 sigma_dut_print(global_dut, DUT_MSG_INFO, 1630 "Printing Mesh Id:"); 1631 nan_hex_dump(global_dut, 1632 event->discovery_attr[idx].mesh_id, 1633 event->discovery_attr[idx].mesh_id_len); 1634 sigma_dut_print(global_dut, DUT_MSG_INFO, 1635 "Printing Infrastructure Ssid:"); 1636 nan_hex_dump(global_dut, 1637 event->discovery_attr[idx].infrastructure_ssid_val, 1638 event->discovery_attr[idx].infrastructure_ssid_len); 1639 } 1640 } else { 1641 sigma_dut_print(global_dut, DUT_MSG_INFO, 1642 "PostDiscovery attribute not present"); 1643 } 1644 1645 /* Print the fam */ 1646 if (event->num_chans) { 1647 nan_print_further_availability_chan(global_dut, 1648 event->num_chans, 1649 &event->famchan[0]); 1650 } else { 1651 sigma_dut_print(global_dut, DUT_MSG_INFO, 1652 "Further Availability Map not present"); 1653 } 1654 if (event->cluster_attribute_len) { 1655 sigma_dut_print(global_dut, DUT_MSG_INFO, 1656 "Printing Cluster Attribute:"); 1657 nan_hex_dump(global_dut, event->cluster_attribute, 1658 event->cluster_attribute_len); 1659 } else { 1660 sigma_dut_print(global_dut, DUT_MSG_INFO, 1661 "Cluster Attribute not present"); 1662 } 1663 } 1664 1665 1666 /* Events Callback */ 1667 void nan_event_match_expired(NanMatchExpiredInd *event) 1668 { 1669 sigma_dut_print(global_dut, DUT_MSG_INFO, 1670 "%s: publish_subscribe_id %d match_handle %08x", 1671 __func__, event->publish_subscribe_id, 1672 event->requestor_instance_id); 1673 } 1674 1675 1676 /* Events Callback */ 1677 void nan_event_subscribe_terminated(NanSubscribeTerminatedInd *event) 1678 { 1679 sigma_dut_print(global_dut, DUT_MSG_INFO, 1680 "%s: Subscribe Id %d reason %d", 1681 __func__, event->subscribe_id, event->reason); 1682 } 1683 1684 1685 /* Events Callback */ 1686 void nan_event_followup(NanFollowupInd *event) 1687 { 1688 sigma_dut_print(global_dut, DUT_MSG_INFO, 1689 "%s: Publish/Subscribe Id %d match_handle 0x%08x dw_or_faw %d " 1690 MAC_ADDR_STR, __func__, event->publish_subscribe_id, 1691 event->requestor_instance_id, event->dw_or_faw, 1692 MAC_ADDR_ARRAY(event->addr)); 1693 1694 global_match_handle = event->publish_subscribe_id; 1695 global_header_handle = event->requestor_instance_id; 1696 sigma_dut_print(global_dut, DUT_MSG_INFO, "%s: Printing SSI", __func__); 1697 nan_hex_dump(global_dut, event->service_specific_info, 1698 event->service_specific_info_len); 1699 event_anyresponse = 1; 1700 snprintf(global_event_resp_buf, sizeof(global_event_resp_buf), 1701 "EventName,FollowUp,RemoteInstanceID,%d,LocalInstanceID,%d,mac," 1702 MAC_ADDR_STR " ", event->requestor_instance_id >> 24, 1703 event->publish_subscribe_id, MAC_ADDR_ARRAY(event->addr)); 1704 } 1705 1706 1707 /* Events Callback */ 1708 void nan_event_disceng_event(NanDiscEngEventInd *event) 1709 { 1710 sigma_dut_print(global_dut, DUT_MSG_INFO, "%s: event_type %d", 1711 __func__, event->event_type); 1712 1713 if (event->event_type == NAN_EVENT_ID_JOINED_CLUSTER) { 1714 sigma_dut_print(global_dut, DUT_MSG_INFO, "%s: Joined cluster " 1715 MAC_ADDR_STR, 1716 __func__, 1717 MAC_ADDR_ARRAY(event->data.cluster.addr)); 1718 /* To ensure sta_get_events to get the events 1719 * only after joining the NAN cluster. */ 1720 pthread_cond_signal(&gCondition); 1721 } 1722 if (event->event_type == NAN_EVENT_ID_STARTED_CLUSTER) { 1723 sigma_dut_print(global_dut, DUT_MSG_INFO, 1724 "%s: Started cluster " MAC_ADDR_STR, 1725 __func__, 1726 MAC_ADDR_ARRAY(event->data.cluster.addr)); 1727 } 1728 if (event->event_type == NAN_EVENT_ID_DISC_MAC_ADDR) { 1729 sigma_dut_print(global_dut, DUT_MSG_INFO, 1730 "%s: Discovery Mac Address " 1731 MAC_ADDR_STR, 1732 __func__, 1733 MAC_ADDR_ARRAY(event->data.mac_addr.addr)); 1734 memcpy(global_nan_mac_addr, event->data.mac_addr.addr, 1735 sizeof(global_nan_mac_addr)); 1736 } 1737 } 1738 1739 1740 /* Events Callback */ 1741 void nan_event_disabled(NanDisabledInd *event) 1742 { 1743 sigma_dut_print(global_dut, DUT_MSG_INFO, "%s: reason %d", 1744 __func__, event->reason); 1745 /* pthread_cond_signal(&gCondition); */ 1746 } 1747 1748 1749 /* Events callback */ 1750 static void ndp_event_data_indication(NanDataPathRequestInd *event) 1751 { 1752 sigma_dut_print(global_dut, DUT_MSG_INFO, 1753 "%s: Service Instance Id: %d Peer Discovery MAC ADDR " 1754 MAC_ADDR_STR 1755 " NDP Instance Id: %d App Info len %d App Info %s", 1756 __func__, 1757 event->service_instance_id, 1758 MAC_ADDR_ARRAY(event->peer_disc_mac_addr), 1759 event->ndp_instance_id, 1760 event->app_info.ndp_app_info_len, 1761 event->app_info.ndp_app_info); 1762 1763 global_ndp_instance_id = event->ndp_instance_id; 1764 } 1765 1766 1767 /* Events callback */ 1768 static void ndp_event_data_confirm(NanDataPathConfirmInd *event) 1769 { 1770 char cmd[200]; 1771 char ipv6_buf[100]; 1772 1773 sigma_dut_print(global_dut, DUT_MSG_INFO, 1774 "Received NDP Confirm Indication"); 1775 1776 memset(cmd, 0, sizeof(cmd)); 1777 memset(ipv6_buf, 0, sizeof(ipv6_buf)); 1778 1779 global_ndp_instance_id = event->ndp_instance_id; 1780 1781 if (event->rsp_code == NAN_DP_REQUEST_ACCEPT) { 1782 if (system("ifconfig nan0 up") != 0) { 1783 sigma_dut_print(global_dut, DUT_MSG_ERROR, 1784 "Failed to set nan interface up"); 1785 return; 1786 } 1787 if (system("ip -6 route add fe80::/64 dev nan0 table local") != 1788 0) { 1789 sigma_dut_print(global_dut, DUT_MSG_ERROR, 1790 "Failed to run:ip -6 route replace fe80::/64 dev nan0 table local"); 1791 } 1792 convert_mac_addr_to_ipv6_lladdr(event->peer_ndi_mac_addr, 1793 ipv6_buf, sizeof(ipv6_buf)); 1794 snprintf(cmd, sizeof(cmd), 1795 "ip -6 neighbor replace %s lladdr %02x:%02x:%02x:%02x:%02x:%02x nud permanent dev nan0", 1796 ipv6_buf, event->peer_ndi_mac_addr[0], 1797 event->peer_ndi_mac_addr[1], 1798 event->peer_ndi_mac_addr[2], 1799 event->peer_ndi_mac_addr[3], 1800 event->peer_ndi_mac_addr[4], 1801 event->peer_ndi_mac_addr[5]); 1802 sigma_dut_print(global_dut, DUT_MSG_INFO, 1803 "neighbor replace cmd = %s", cmd); 1804 if (system(cmd) != 0) { 1805 sigma_dut_print(global_dut, DUT_MSG_ERROR, 1806 "Failed to run: ip -6 neighbor replace"); 1807 return; 1808 } 1809 } 1810 } 1811 1812 1813 void * my_thread_function(void *ptr) 1814 { 1815 wifi_event_loop(global_wifi_handle); 1816 pthread_exit(0); 1817 return (void *) NULL; 1818 } 1819 1820 1821 static NanCallbackHandler callbackHandler = { 1822 .NotifyResponse = nan_notify_response, 1823 .EventPublishReplied = nan_event_publish_replied, 1824 .EventPublishTerminated = nan_event_publish_terminated, 1825 .EventMatch = nan_event_match, 1826 .EventMatchExpired = nan_event_match_expired, 1827 .EventSubscribeTerminated = nan_event_subscribe_terminated, 1828 .EventFollowup = nan_event_followup, 1829 .EventDiscEngEvent = nan_event_disceng_event, 1830 .EventDisabled = nan_event_disabled, 1831 .EventDataRequest = ndp_event_data_indication, 1832 .EventDataConfirm = ndp_event_data_confirm, 1833 }; 1834 1835 1836 void nan_init(struct sigma_dut *dut) 1837 { 1838 pthread_t thread1; /* thread variables */ 1839 wifi_error err = wifi_initialize(&global_wifi_handle); 1840 1841 if (err) { 1842 printf("wifi hal initialize failed\n"); 1843 return; 1844 } 1845 1846 global_interface_handle = wifi_get_iface_handle(global_wifi_handle, 1847 (char *) "wlan0"); 1848 /* create threads 1 */ 1849 pthread_create(&thread1, NULL, &my_thread_function, NULL); 1850 1851 pthread_mutex_init(&gMutex, NULL); 1852 pthread_cond_init(&gCondition, NULL); 1853 if (global_interface_handle) 1854 nan_register_handler(global_interface_handle, callbackHandler); 1855 } 1856 1857 1858 void nan_cmd_sta_reset_default(struct sigma_dut *dut, struct sigma_conn *conn, 1859 struct sigma_cmd *cmd) 1860 { 1861 sigma_dut_print(dut, DUT_MSG_INFO, "NAN sta_reset_default"); 1862 1863 if (nan_state == 0) { 1864 nan_init(dut); 1865 nan_state = 1; 1866 } 1867 is_fam = 0; 1868 event_anyresponse = 0; 1869 global_dut = dut; 1870 memset(&dut->nan_pmk[0], 0, NAN_PMK_INFO_LEN); 1871 dut->nan_pmk_len = 0; 1872 dut->sta_channel = 0; 1873 memset(global_event_resp_buf, 0, sizeof(global_event_resp_buf)); 1874 memset(&global_nan_sync_stats, 0, sizeof(global_nan_sync_stats)); 1875 memset(global_publish_service_name, 0, 1876 sizeof(global_publish_service_name)); 1877 global_publish_service_name_len = 0; 1878 global_publish_id = 0; 1879 global_subscribe_id = 0; 1880 1881 sigma_nan_data_end(dut, cmd); 1882 nan_data_interface_delete(0, global_interface_handle, (char *) "nan0"); 1883 sigma_nan_disable(dut, conn, cmd); 1884 } 1885 1886 1887 int nan_cmd_sta_exec_action(struct sigma_dut *dut, struct sigma_conn *conn, 1888 struct sigma_cmd *cmd) 1889 { 1890 const char *program = get_param(cmd, "Prog"); 1891 const char *nan_op = get_param(cmd, "NANOp"); 1892 const char *method_type = get_param(cmd, "MethodType"); 1893 const char *band = get_param(cmd, "band"); 1894 char resp_buf[100]; 1895 wifi_error ret; 1896 1897 if (program == NULL) 1898 return -1; 1899 1900 if (strcasecmp(program, "NAN") != 0) { 1901 send_resp(dut, conn, SIGMA_ERROR, 1902 "ErrorCode,Unsupported program"); 1903 return 0; 1904 } 1905 1906 if (nan_op) { 1907 /* 1908 * NANOp has been specified. 1909 * We will build a nan_enable or nan_disable command. 1910 */ 1911 if (strcasecmp(nan_op, "On") == 0) { 1912 if (sigma_nan_enable(dut, conn, cmd) == 0) { 1913 ret = nan_data_interface_create( 1914 0, global_interface_handle, 1915 (char *) "nan0"); 1916 if (ret != WIFI_SUCCESS) { 1917 sigma_dut_print( 1918 global_dut, DUT_MSG_ERROR, 1919 "Unable to create NAN data interface"); 1920 } 1921 snprintf(resp_buf, sizeof(resp_buf), "mac," 1922 MAC_ADDR_STR, 1923 MAC_ADDR_ARRAY(global_nan_mac_addr)); 1924 send_resp(dut, conn, SIGMA_COMPLETE, resp_buf); 1925 } else { 1926 send_resp(dut, conn, SIGMA_ERROR, 1927 "NAN_ENABLE_FAILED"); 1928 return -1; 1929 } 1930 1931 if (band && strcasecmp(band, "24g") == 0) { 1932 sigma_dut_print(dut, DUT_MSG_INFO, 1933 "%s: Setting band to 2G Only", 1934 __func__); 1935 sigma_ndp_configure_band( 1936 dut, conn, cmd, 1937 NAN_DATA_PATH_SUPPORTED_BAND_2G); 1938 } else if (band && dut->sta_channel > 12) { 1939 sigma_ndp_configure_band( 1940 dut, conn, cmd, 1941 NAN_DATA_PATH_SUPPORT_DUAL_BAND); 1942 } 1943 } else if (strcasecmp(nan_op, "Off") == 0) { 1944 sigma_nan_disable(dut, conn, cmd); 1945 memset(global_publish_service_name, 0, 1946 sizeof(global_publish_service_name)); 1947 global_publish_service_name_len = 0; 1948 global_publish_id = 0; 1949 global_subscribe_id = 0; 1950 send_resp(dut, conn, SIGMA_COMPLETE, "NULL"); 1951 } 1952 } 1953 if (nan_state && nan_op == NULL) { 1954 if (method_type) { 1955 if (strcasecmp(method_type, "Publish") == 0) { 1956 sigma_nan_publish_request(dut, conn, cmd); 1957 send_resp(dut, conn, SIGMA_COMPLETE, "NULL"); 1958 } 1959 if (strcasecmp(method_type, "Subscribe") == 0) { 1960 sigma_nan_subscribe_request(dut, conn, cmd); 1961 send_resp(dut, conn, SIGMA_COMPLETE, "NULL"); 1962 } 1963 if (strcasecmp(method_type, "Followup") == 0) { 1964 sigma_nan_transmit_followup(dut, conn, cmd); 1965 send_resp(dut, conn, SIGMA_COMPLETE, "NULL"); 1966 } 1967 if (strcasecmp(method_type, "DataRequest") == 0) { 1968 sigma_nan_data_request(dut, conn, cmd); 1969 send_resp(dut, conn, SIGMA_COMPLETE, "NULL"); 1970 } 1971 if (strcasecmp(method_type, "DataResponse") == 0) { 1972 sigma_dut_print(dut, DUT_MSG_INFO, 1973 "%s: method_type is DataResponse", 1974 __func__); 1975 sigma_nan_data_response(dut, conn, cmd); 1976 send_resp(dut, conn, SIGMA_COMPLETE, "NULL"); 1977 } 1978 if (strcasecmp(method_type, "DataEnd") == 0) { 1979 sigma_nan_data_end(dut, cmd); 1980 send_resp(dut, conn, SIGMA_COMPLETE, "NULL"); 1981 } 1982 if (strcasecmp(method_type, "rangerequest") == 0) { 1983 sigma_dut_print(dut, DUT_MSG_INFO, 1984 "%s: method_type is rangerequest", 1985 __func__); 1986 sigma_nan_range_request(dut, cmd); 1987 send_resp(dut, conn, SIGMA_COMPLETE, "NULL"); 1988 } 1989 if (strcasecmp(method_type, "cancelrange") == 0) { 1990 sigma_dut_print(dut, DUT_MSG_INFO, 1991 "%s: method_type is cancelrange", 1992 __func__); 1993 sigma_nan_cancel_range(dut, cmd); 1994 send_resp(dut, conn, SIGMA_COMPLETE, "NULL"); 1995 } 1996 if (strcasecmp(method_type, "SchedUpdate") == 0) { 1997 sigma_dut_print(dut, DUT_MSG_INFO, 1998 "%s: method_type is SchedUpdate", 1999 __func__); 2000 sigma_nan_schedule_update(dut, cmd); 2001 send_resp(dut, conn, SIGMA_COMPLETE, "NULL"); 2002 } 2003 } else { 2004 sigma_nan_config_enable(dut, conn, cmd); 2005 snprintf(resp_buf, sizeof(resp_buf), "mac," 2006 MAC_ADDR_STR, 2007 MAC_ADDR_ARRAY(global_nan_mac_addr)); 2008 send_resp(dut, conn, SIGMA_COMPLETE, resp_buf); 2009 } 2010 } 2011 2012 return 0; 2013 } 2014 2015 2016 int nan_cmd_sta_get_parameter(struct sigma_dut *dut, struct sigma_conn *conn, 2017 struct sigma_cmd *cmd) 2018 { 2019 2020 const char *program = get_param(cmd, "Program"); 2021 const char *parameter = get_param(cmd, "Parameter"); 2022 char resp_buf[100]; 2023 NanStatsRequest req; 2024 struct timespec abstime; 2025 u64 master_rank; 2026 u8 master_pref; 2027 u8 random_factor; 2028 u8 hop_count; 2029 u32 beacon_transmit_time; 2030 u32 ndp_channel_freq; 2031 u32 ndp_channel_freq2; 2032 2033 if (program == NULL) { 2034 sigma_dut_print(dut, DUT_MSG_ERROR, "Invalid Program Name"); 2035 return -1; 2036 } 2037 if (strcasecmp(program, "NAN") != 0) { 2038 send_resp(dut, conn, SIGMA_ERROR, 2039 "ErrorCode,Unsupported program"); 2040 return 0; 2041 } 2042 2043 if (parameter == NULL) { 2044 sigma_dut_print(dut, DUT_MSG_ERROR, "Invalid Parameter"); 2045 return -1; 2046 } 2047 2048 memset(&req, 0, sizeof(NanStatsRequest)); 2049 req.stats_type = (NanStatsType) NAN_STATS_ID_DE_TIMING_SYNC; 2050 nan_stats_request(0, global_interface_handle, &req); 2051 /* 2052 * To ensure sta_get_events to get the events 2053 * only after joining the NAN cluster 2054 */ 2055 abstime.tv_sec = 4; 2056 abstime.tv_nsec = 0; 2057 wait(abstime); 2058 2059 master_rank = global_nan_sync_stats.myRank; 2060 master_pref = (global_nan_sync_stats.myRank & 0xFF00000000000000) >> 56; 2061 random_factor = (global_nan_sync_stats.myRank & 0x00FF000000000000) >> 2062 48; 2063 hop_count = global_nan_sync_stats.currAmHopCount; 2064 beacon_transmit_time = global_nan_sync_stats.currAmBTT; 2065 ndp_channel_freq = global_nan_sync_stats.ndpChannelFreq; 2066 ndp_channel_freq2 = global_nan_sync_stats.ndpChannelFreq2; 2067 2068 sigma_dut_print(dut, DUT_MSG_INFO, 2069 "%s: NanStatsRequest Master_pref:%02x, Random_factor:%02x, hop_count:%02x beacon_transmit_time:%d ndp_channel_freq:%d ndp_channel_freq2:%d", 2070 __func__, master_pref, random_factor, 2071 hop_count, beacon_transmit_time, 2072 ndp_channel_freq, ndp_channel_freq2); 2073 2074 if (strcasecmp(parameter, "MasterPref") == 0) { 2075 snprintf(resp_buf, sizeof(resp_buf), "MasterPref,0x%x", 2076 master_pref); 2077 } else if (strcasecmp(parameter, "MasterRank") == 0) { 2078 snprintf(resp_buf, sizeof(resp_buf), "MasterRank,0x%lx", 2079 master_rank); 2080 } else if (strcasecmp(parameter, "RandFactor") == 0) { 2081 snprintf(resp_buf, sizeof(resp_buf), "RandFactor,0x%x", 2082 random_factor); 2083 } else if (strcasecmp(parameter, "HopCount") == 0) { 2084 snprintf(resp_buf, sizeof(resp_buf), "HopCount,0x%x", 2085 hop_count); 2086 } else if (strcasecmp(parameter, "BeaconTransTime") == 0) { 2087 snprintf(resp_buf, sizeof(resp_buf), "BeaconTransTime 0x%x", 2088 beacon_transmit_time); 2089 } else if (strcasecmp(parameter, "NANStatus") == 0) { 2090 if (nan_state == 1) 2091 snprintf(resp_buf, sizeof(resp_buf), "On"); 2092 else 2093 snprintf(resp_buf, sizeof(resp_buf), "Off"); 2094 } else if (strcasecmp(parameter, "NDPChannel") == 0) { 2095 if (ndp_channel_freq != 0 && ndp_channel_freq2 != 0) { 2096 snprintf(resp_buf, sizeof(resp_buf), 2097 "ndpchannel,%d,ndpchannel,%d", 2098 freq_to_channel(ndp_channel_freq), 2099 freq_to_channel(ndp_channel_freq2)); 2100 } else if (ndp_channel_freq != 0) { 2101 snprintf(resp_buf, sizeof(resp_buf), "ndpchannel,%d", 2102 freq_to_channel(ndp_channel_freq)); 2103 } else if (ndp_channel_freq2 != 0) { 2104 snprintf(resp_buf, sizeof(resp_buf), "ndpchannel,%d", 2105 freq_to_channel(ndp_channel_freq2)); 2106 } else { 2107 sigma_dut_print(dut, DUT_MSG_ERROR, 2108 "%s: No Negotiated NDP Channels", __func__); 2109 } 2110 } else { 2111 send_resp(dut, conn, SIGMA_ERROR, "Invalid Parameter"); 2112 return 0; 2113 } 2114 2115 send_resp(dut, conn, SIGMA_COMPLETE, resp_buf); 2116 return 0; 2117 } 2118 2119 2120 int nan_cmd_sta_get_events(struct sigma_dut *dut, struct sigma_conn *conn, 2121 struct sigma_cmd *cmd) 2122 { 2123 const char *action = get_param(cmd, "Action"); 2124 2125 if (!action) 2126 return 0; 2127 2128 /* Check action for start, stop and get events. */ 2129 if (strcasecmp(action, "Start") == 0) { 2130 memset(global_event_resp_buf, 0, sizeof(global_event_resp_buf)); 2131 send_resp(dut, conn, SIGMA_COMPLETE, NULL); 2132 } else if (strcasecmp(action, "Stop") == 0) { 2133 event_anyresponse = 0; 2134 memset(global_event_resp_buf, 0, sizeof(global_event_resp_buf)); 2135 send_resp(dut, conn, SIGMA_COMPLETE, NULL); 2136 } else if (strcasecmp(action, "Get") == 0) { 2137 if (event_anyresponse == 1) { 2138 send_resp(dut, conn, SIGMA_COMPLETE, 2139 global_event_resp_buf); 2140 } else { 2141 send_resp(dut, conn, SIGMA_COMPLETE, "EventList,NONE"); 2142 } 2143 } 2144 return 0; 2145 } 2146 2147 #else /* #if NAN_CERT_VERSION */ 2148 2149 int nan_cmd_sta_preset_testparameters(struct sigma_dut *dut, 2150 struct sigma_conn *conn, 2151 struct sigma_cmd *cmd) 2152 { 2153 return 1; 2154 } 2155 2156 2157 int nan_cmd_sta_get_parameter(struct sigma_dut *dut, struct sigma_conn *conn, 2158 struct sigma_cmd *cmd) 2159 { 2160 return 0; 2161 2162 } 2163 2164 2165 void nan_cmd_sta_reset_default(struct sigma_dut *dut, struct sigma_conn *conn, 2166 struct sigma_cmd *cmd) 2167 { 2168 return; 2169 } 2170 2171 2172 int nan_cmd_sta_get_events(struct sigma_dut *dut, struct sigma_conn *conn, 2173 struct sigma_cmd *cmd) 2174 { 2175 return 0; 2176 } 2177 2178 2179 int nan_cmd_sta_exec_action(struct sigma_dut *dut, struct sigma_conn *conn, 2180 struct sigma_cmd *cmd) 2181 { 2182 return 0; 2183 } 2184 2185 #endif /* #if NAN_CERT_VERSION */ 2186