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