1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "sync.h" 18 #include <utils/Log.h> 19 #include <errno.h> 20 #include "wifi_hal.h" 21 #include "nan_i.h" 22 #include "nancommand.h" 23 #include "qca-vendor.h" 24 #include <errno.h> 25 26 //Function which calls the necessaryIndication callback 27 //based on the indication type 28 int NanCommand::handleNanIndication() 29 { 30 //Based on the message_id in the header determine the Indication type 31 //and call the necessary callback handler 32 u16 msg_id; 33 int res = 0; 34 35 msg_id = getIndicationType(); 36 37 ALOGV("handleNanIndication msg_id:%u", msg_id); 38 switch (msg_id) { 39 case NAN_INDICATION_PUBLISH_TERMINATED: 40 NanPublishTerminatedInd publishTerminatedInd; 41 memset(&publishTerminatedInd, 0, sizeof(publishTerminatedInd)); 42 res = getNanPublishTerminated(&publishTerminatedInd); 43 if (!res && mHandler.EventPublishTerminated) { 44 (*mHandler.EventPublishTerminated)(&publishTerminatedInd); 45 } 46 break; 47 48 case NAN_INDICATION_MATCH: 49 NanMatchInd matchInd; 50 memset(&matchInd, 0, sizeof(matchInd)); 51 res = getNanMatch(&matchInd); 52 if (!res && mHandler.EventMatch) { 53 (*mHandler.EventMatch)(&matchInd); 54 } 55 break; 56 57 case NAN_INDICATION_MATCH_EXPIRED: 58 NanMatchExpiredInd matchExpiredInd; 59 memset(&matchExpiredInd, 0, sizeof(matchExpiredInd)); 60 res = getNanMatchExpired(&matchExpiredInd); 61 if (!res && mHandler.EventMatchExpired) { 62 (*mHandler.EventMatchExpired)(&matchExpiredInd); 63 } 64 break; 65 66 case NAN_INDICATION_SUBSCRIBE_TERMINATED: 67 NanSubscribeTerminatedInd subscribeTerminatedInd; 68 memset(&subscribeTerminatedInd, 0, sizeof(subscribeTerminatedInd)); 69 res = getNanSubscribeTerminated(&subscribeTerminatedInd); 70 if (!res && mHandler.EventSubscribeTerminated) { 71 (*mHandler.EventSubscribeTerminated)(&subscribeTerminatedInd); 72 } 73 break; 74 75 case NAN_INDICATION_DE_EVENT: 76 NanDiscEngEventInd discEngEventInd; 77 memset(&discEngEventInd, 0, sizeof(discEngEventInd)); 78 res = getNanDiscEngEvent(&discEngEventInd); 79 if (!res && mHandler.EventDiscEngEvent) { 80 (*mHandler.EventDiscEngEvent)(&discEngEventInd); 81 } 82 break; 83 84 case NAN_INDICATION_FOLLOWUP: 85 NanFollowupInd followupInd; 86 memset(&followupInd, 0, sizeof(followupInd)); 87 res = getNanFollowup(&followupInd); 88 if (!res && mHandler.EventFollowup) { 89 (*mHandler.EventFollowup)(&followupInd); 90 } 91 break; 92 93 case NAN_INDICATION_DISABLED: 94 NanDisabledInd disabledInd; 95 memset(&disabledInd, 0, sizeof(disabledInd)); 96 res = getNanDisabled(&disabledInd); 97 if (!res && mHandler.EventDisabled) { 98 (*mHandler.EventDisabled)(&disabledInd); 99 } 100 break; 101 102 case NAN_INDICATION_TCA: 103 NanTCAInd tcaInd; 104 memset(&tcaInd, 0, sizeof(tcaInd)); 105 res = getNanTca(&tcaInd); 106 if (!res && mHandler.EventTca) { 107 (*mHandler.EventTca)(&tcaInd); 108 } 109 break; 110 111 case NAN_INDICATION_BEACON_SDF_PAYLOAD: 112 NanBeaconSdfPayloadInd beaconSdfPayloadInd; 113 memset(&beaconSdfPayloadInd, 0, sizeof(beaconSdfPayloadInd)); 114 res = getNanBeaconSdfPayload(&beaconSdfPayloadInd); 115 if (!res && mHandler.EventBeaconSdfPayload) { 116 (*mHandler.EventBeaconSdfPayload)(&beaconSdfPayloadInd); 117 } 118 break; 119 120 default: 121 ALOGE("handleNanIndication error invalid msg_id:%u", msg_id); 122 res = (int)WIFI_ERROR_INVALID_REQUEST_ID; 123 break; 124 } 125 return res; 126 } 127 128 //Function which will return the Nan Indication type based on 129 //the initial few bytes of mNanVendorEvent 130 NanIndicationType NanCommand::getIndicationType() 131 { 132 if (mNanVendorEvent == NULL) { 133 ALOGE("%s: Invalid argument mNanVendorEvent:%p", 134 __func__, mNanVendorEvent); 135 return NAN_INDICATION_UNKNOWN; 136 } 137 138 NanMsgHeader *pHeader = (NanMsgHeader *)mNanVendorEvent; 139 140 switch (pHeader->msgId) { 141 case NAN_MSG_ID_PUBLISH_REPLIED_IND: 142 return NAN_INDICATION_UNKNOWN; 143 case NAN_MSG_ID_PUBLISH_TERMINATED_IND: 144 return NAN_INDICATION_PUBLISH_TERMINATED; 145 case NAN_MSG_ID_MATCH_IND: 146 return NAN_INDICATION_MATCH; 147 case NAN_MSG_ID_MATCH_EXPIRED_IND: 148 return NAN_INDICATION_MATCH_EXPIRED; 149 case NAN_MSG_ID_FOLLOWUP_IND: 150 return NAN_INDICATION_FOLLOWUP; 151 case NAN_MSG_ID_SUBSCRIBE_TERMINATED_IND: 152 return NAN_INDICATION_SUBSCRIBE_TERMINATED; 153 case NAN_MSG_ID_DE_EVENT_IND: 154 return NAN_INDICATION_DE_EVENT; 155 case NAN_MSG_ID_DISABLE_IND: 156 return NAN_INDICATION_DISABLED; 157 case NAN_MSG_ID_TCA_IND: 158 return NAN_INDICATION_TCA; 159 case NAN_MSG_ID_BEACON_SDF_IND: 160 return NAN_INDICATION_BEACON_SDF_PAYLOAD; 161 default: 162 return NAN_INDICATION_UNKNOWN; 163 } 164 } 165 166 int NanCommand::getNanPublishTerminated(NanPublishTerminatedInd *event) 167 { 168 if (event == NULL || mNanVendorEvent == NULL) { 169 ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p", 170 __func__, event, mNanVendorEvent); 171 return WIFI_ERROR_INVALID_ARGS; 172 } 173 174 pNanPublishTerminatedIndMsg pRsp = (pNanPublishTerminatedIndMsg)mNanVendorEvent; 175 event->publish_id = pRsp->fwHeader.handle; 176 event->reason = (NanStatusType)pRsp->reason; 177 return WIFI_SUCCESS; 178 } 179 180 int NanCommand::getNanMatch(NanMatchInd *event) 181 { 182 if (event == NULL || mNanVendorEvent == NULL) { 183 ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p", 184 __func__, event, mNanVendorEvent); 185 return WIFI_ERROR_INVALID_ARGS; 186 } 187 188 pNanMatchIndMsg pRsp = (pNanMatchIndMsg)mNanVendorEvent; 189 event->publish_subscribe_id = pRsp->fwHeader.handle; 190 event->requestor_instance_id = pRsp->matchIndParams.matchHandle; 191 event->match_occured_flag = pRsp->matchIndParams.matchOccuredFlag; 192 event->out_of_resource_flag = pRsp->matchIndParams.outOfResourceFlag; 193 194 u8 *pInputTlv = pRsp->ptlv; 195 NanTlv outputTlv; 196 u16 readLen = 0; 197 int remainingLen = (mNanDataLen - \ 198 (sizeof(NanMsgHeader) + sizeof(NanMatchIndParams))); 199 int ret = 0, idx = 0; 200 201 //Has SDF match filter and service specific info TLV 202 if (remainingLen <= 0) { 203 ALOGV("%s: No TLV's present",__func__); 204 return WIFI_SUCCESS; 205 } 206 ALOGV("%s: TLV remaining Len:%d",__func__, remainingLen); 207 while ((remainingLen > 0) && 208 (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) { 209 ALOGV("%s: Remaining Len:%d readLen:%d type:%d length:%d", 210 __func__, remainingLen, readLen, outputTlv.type, 211 outputTlv.length); 212 switch (outputTlv.type) { 213 case NAN_TLV_TYPE_SERVICE_SPECIFIC_INFO: 214 if (outputTlv.length > NAN_MAX_SERVICE_NAME_LEN) { 215 outputTlv.length = NAN_MAX_SERVICE_NAME_LEN; 216 } 217 event->service_specific_info_len = outputTlv.length; 218 memcpy(event->service_specific_info, outputTlv.value, 219 outputTlv.length); 220 break; 221 case NAN_TLV_TYPE_SDF_MATCH_FILTER: 222 if (outputTlv.length > NAN_MAX_MATCH_FILTER_LEN) { 223 outputTlv.length = NAN_MAX_MATCH_FILTER_LEN; 224 } 225 event->sdf_match_filter_len = outputTlv.length; 226 memcpy(event->sdf_match_filter, outputTlv.value, 227 outputTlv.length); 228 break; 229 case NAN_TLV_TYPE_MAC_ADDRESS: 230 if (outputTlv.length > sizeof(event->addr)) { 231 outputTlv.length = sizeof(event->addr); 232 } 233 memcpy(event->addr, outputTlv.value, outputTlv.length); 234 break; 235 case NAN_TLV_TYPE_RECEIVED_RSSI_VALUE: 236 if (outputTlv.length > sizeof(event->rssi_value)) { 237 outputTlv.length = sizeof(event->rssi_value); 238 } 239 memcpy(&event->rssi_value, outputTlv.value, 240 outputTlv.length); 241 break; 242 case NAN_TLV_TYPE_POST_NAN_CONNECTIVITY_CAPABILITIES_RECEIVE: 243 if (outputTlv.length != sizeof(u32)) { 244 ALOGE("NAN_TLV_TYPE_POST_NAN_CONNECTIVITY_CAPABILITIES_RECEIVE" 245 "Incorrect size:%d expecting %zu", outputTlv.length, 246 sizeof(u32)); 247 break; 248 } 249 event->is_conn_capability_valid = 1; 250 /* Populate conn_capability from received TLV */ 251 getNanReceivePostConnectivityCapabilityVal(outputTlv.value, 252 &event->conn_capability); 253 break; 254 case NAN_TLV_TYPE_POST_NAN_DISCOVERY_ATTRIBUTE_RECEIVE: 255 /* Populate receive discovery attribute from 256 received TLV */ 257 idx = event->num_rx_discovery_attr; 258 ret = getNanReceivePostDiscoveryVal(outputTlv.value, 259 outputTlv.length, 260 &event->discovery_attr[idx]); 261 if (ret == 0) { 262 event->num_rx_discovery_attr++; 263 } 264 else { 265 ALOGE("NAN_TLV_TYPE_POST_NAN_DISCOVERY_ATTRIBUTE_RECEIVE" 266 "Incorrect"); 267 } 268 break; 269 case NAN_TLV_TYPE_FURTHER_AVAILABILITY_MAP: 270 /* Populate further availability bitmap from 271 received TLV */ 272 ret = getNanFurtherAvailabilityMap(outputTlv.value, 273 outputTlv.length, 274 &event->num_chans, 275 &event->famchan[0]); 276 if (ret < 0) 277 ALOGE("NAN_TLV_TYPE_FURTHER_AVAILABILITY_MAP" 278 "Incorrect"); 279 break; 280 case NAN_TLV_TYPE_CLUSTER_ATTRIBUTE: 281 if (outputTlv.length > sizeof(event->cluster_attribute)) { 282 outputTlv.length = sizeof(event->cluster_attribute); 283 } 284 memcpy(event->cluster_attribute, 285 outputTlv.value, outputTlv.length); 286 event->cluster_attribute_len = outputTlv.length; 287 break; 288 default: 289 ALOGV("Unknown TLV type skipped"); 290 break; 291 } 292 remainingLen -= readLen; 293 pInputTlv += readLen; 294 memset(&outputTlv, 0, sizeof(outputTlv)); 295 } 296 return WIFI_SUCCESS; 297 } 298 299 int NanCommand::getNanMatchExpired(NanMatchExpiredInd *event) 300 { 301 if (event == NULL || mNanVendorEvent == NULL) { 302 ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p", 303 __func__, event, mNanVendorEvent); 304 return WIFI_ERROR_INVALID_ARGS; 305 } 306 307 pNanMatchExpiredIndMsg pRsp = (pNanMatchExpiredIndMsg)mNanVendorEvent; 308 event->publish_subscribe_id = pRsp->fwHeader.handle; 309 event->requestor_instance_id = pRsp->matchExpiredIndParams.matchHandle; 310 return WIFI_SUCCESS; 311 } 312 313 int NanCommand::getNanSubscribeTerminated(NanSubscribeTerminatedInd *event) 314 { 315 if (event == NULL || mNanVendorEvent == NULL) { 316 ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p", 317 __func__, event, mNanVendorEvent); 318 return WIFI_ERROR_INVALID_ARGS; 319 } 320 321 pNanSubscribeTerminatedIndMsg pRsp = (pNanSubscribeTerminatedIndMsg)mNanVendorEvent; 322 event->subscribe_id = pRsp->fwHeader.handle; 323 event->reason = (NanStatusType)pRsp->reason; 324 return WIFI_SUCCESS; 325 } 326 327 int NanCommand::getNanFollowup(NanFollowupInd *event) 328 { 329 if (event == NULL || mNanVendorEvent == NULL) { 330 ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p", 331 __func__, event, mNanVendorEvent); 332 return WIFI_ERROR_INVALID_ARGS; 333 } 334 335 pNanFollowupIndMsg pRsp = (pNanFollowupIndMsg)mNanVendorEvent; 336 event->publish_subscribe_id = pRsp->fwHeader.handle; 337 event->requestor_instance_id = pRsp->followupIndParams.matchHandle; 338 event->dw_or_faw = pRsp->followupIndParams.window; 339 340 u8 *pInputTlv = pRsp->ptlv; 341 NanTlv outputTlv; 342 u16 readLen = 0; 343 int remainingLen = (mNanDataLen - \ 344 (sizeof(NanMsgHeader) + sizeof(NanFollowupIndParams))); 345 346 //Has service specific info and extended service specific info TLV 347 if (remainingLen <= 0) { 348 ALOGV("%s: No TLV's present",__func__); 349 return WIFI_SUCCESS; 350 } 351 ALOGV("%s: TLV remaining Len:%d",__func__, remainingLen); 352 while ((remainingLen > 0) && 353 (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) { 354 ALOGV("%s: Remaining Len:%d readLen:%d type:%d length:%d", 355 __func__, remainingLen, readLen, outputTlv.type, 356 outputTlv.length); 357 switch (outputTlv.type) { 358 case NAN_TLV_TYPE_SERVICE_SPECIFIC_INFO: 359 case NAN_TLV_TYPE_EXT_SERVICE_SPECIFIC_INFO: 360 if (outputTlv.length > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) { 361 outputTlv.length = NAN_MAX_SERVICE_SPECIFIC_INFO_LEN; 362 } 363 event->service_specific_info_len = outputTlv.length; 364 memcpy(event->service_specific_info, outputTlv.value, 365 outputTlv.length); 366 break; 367 case NAN_TLV_TYPE_MAC_ADDRESS: 368 if (outputTlv.length > sizeof(event->addr)) { 369 outputTlv.length = sizeof(event->addr); 370 } 371 memcpy(event->addr, outputTlv.value, outputTlv.length); 372 break; 373 default: 374 ALOGV("Unknown TLV type skipped"); 375 break; 376 } 377 remainingLen -= readLen; 378 pInputTlv += readLen; 379 memset(&outputTlv, 0, sizeof(outputTlv)); 380 } 381 return WIFI_SUCCESS; 382 } 383 384 int NanCommand::getNanDiscEngEvent(NanDiscEngEventInd *event) 385 { 386 if (event == NULL || mNanVendorEvent == NULL) { 387 ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p", 388 __func__, event, mNanVendorEvent); 389 return WIFI_ERROR_INVALID_ARGS; 390 } 391 392 pNanEventIndMsg pRsp = (pNanEventIndMsg)mNanVendorEvent; 393 memset(&event->data, 0, sizeof(event->data)); 394 395 u8 *pInputTlv = pRsp->ptlv; 396 NanTlv outputTlv; 397 u16 readLen = 0; 398 int remainingLen = (mNanDataLen - \ 399 (sizeof(NanMsgHeader))); 400 401 //Has Self-STA Mac TLV 402 if (remainingLen <= 0) { 403 ALOGE("%s: No TLV's present",__func__); 404 return WIFI_SUCCESS; 405 } 406 407 ALOGV("%s: TLV remaining Len:%d",__func__, remainingLen); 408 while ((remainingLen > 0) && 409 (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) { 410 ALOGV("%s: Remaining Len:%d readLen:%d type:%d length:%d", 411 __func__, remainingLen, readLen, outputTlv.type, 412 outputTlv.length); 413 switch (outputTlv.type) { 414 case NAN_TLV_TYPE_EVENT_SELF_STATION_MAC_ADDRESS: 415 if (outputTlv.length > NAN_MAC_ADDR_LEN) { 416 ALOGV("%s: Reading only first %d bytes of TLV", 417 __func__, NAN_MAC_ADDR_LEN); 418 outputTlv.length = NAN_MAC_ADDR_LEN; 419 } 420 memcpy(event->data.mac_addr.addr, outputTlv.value, 421 outputTlv.length); 422 event->event_type = NAN_EVENT_ID_DISC_MAC_ADDR; 423 break; 424 case NAN_TLV_TYPE_EVENT_STARTED_CLUSTER: 425 if (outputTlv.length > NAN_MAC_ADDR_LEN) { 426 ALOGV("%s: Reading only first %d bytes of TLV", 427 __func__, NAN_MAC_ADDR_LEN); 428 outputTlv.length = NAN_MAC_ADDR_LEN; 429 } 430 memcpy(event->data.cluster.addr, outputTlv.value, 431 outputTlv.length); 432 event->event_type = NAN_EVENT_ID_STARTED_CLUSTER; 433 break; 434 case NAN_TLV_TYPE_EVENT_JOINED_CLUSTER: 435 if (outputTlv.length > NAN_MAC_ADDR_LEN) { 436 ALOGV("%s: Reading only first %d bytes of TLV", 437 __func__, NAN_MAC_ADDR_LEN); 438 outputTlv.length = NAN_MAC_ADDR_LEN; 439 } 440 memcpy(event->data.cluster.addr, outputTlv.value, 441 outputTlv.length); 442 event->event_type = NAN_EVENT_ID_JOINED_CLUSTER; 443 break; 444 default: 445 ALOGV("Unhandled TLV type:%d", outputTlv.type); 446 break; 447 } 448 remainingLen -= readLen; 449 pInputTlv += readLen; 450 memset(&outputTlv,0, sizeof(outputTlv)); 451 } 452 return WIFI_SUCCESS; 453 } 454 455 int NanCommand::getNanDisabled(NanDisabledInd *event) 456 { 457 if (event == NULL || mNanVendorEvent == NULL) { 458 ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p", 459 __func__, event, mNanVendorEvent); 460 return WIFI_ERROR_INVALID_ARGS; 461 } 462 463 pNanDisableIndMsg pRsp = (pNanDisableIndMsg)mNanVendorEvent; 464 event->reason = (NanStatusType)pRsp->reason; 465 return WIFI_SUCCESS; 466 467 } 468 469 int NanCommand::getNanTca(NanTCAInd *event) 470 { 471 if (event == NULL || mNanVendorEvent == NULL) { 472 ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p", 473 __func__, event, mNanVendorEvent); 474 return WIFI_ERROR_INVALID_ARGS; 475 } 476 477 pNanTcaIndMsg pRsp = (pNanTcaIndMsg)mNanVendorEvent; 478 memset(&event->data, 0, sizeof(event->data)); 479 480 u8 *pInputTlv = pRsp->ptlv; 481 NanTlv outputTlv; 482 u16 readLen = 0; 483 484 int remainingLen = (mNanDataLen - \ 485 (sizeof(NanMsgHeader))); 486 487 //Has NAN_TCA_ID_CLUSTER_SIZE 488 if (remainingLen <= 0) { 489 ALOGE("%s: No TLV's present",__func__); 490 return WIFI_SUCCESS; 491 } 492 493 ALOGV("%s: TLV remaining Len:%d",__func__, remainingLen); 494 while ((remainingLen > 0) && 495 (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) { 496 ALOGV("%s: Remaining Len:%d readLen:%d type:%d length:%d", 497 __func__, remainingLen, readLen, outputTlv.type, 498 outputTlv.length); 499 switch (outputTlv.type) { 500 case NAN_TLV_TYPE_CLUSTER_SIZE_RSP: 501 if (outputTlv.length != 2 * sizeof(u32)) { 502 ALOGE("%s: Wrong length %d in Tca Indication expecting %zu bytes", 503 __func__, outputTlv.length, 2 * sizeof(u32)); 504 break; 505 } 506 event->rising_direction_evt_flag = outputTlv.value[0] & 0x01; 507 event->falling_direction_evt_flag = (outputTlv.value[0] & 0x02) >> 1; 508 memcpy(&(event->data.cluster.cluster_size), &outputTlv.value[4], 509 sizeof(event->data.cluster.cluster_size)); 510 event->tca_type = NAN_TCA_ID_CLUSTER_SIZE; 511 break; 512 default: 513 ALOGV("Unhandled TLV type:%d", outputTlv.type); 514 break; 515 } 516 remainingLen -= readLen; 517 pInputTlv += readLen; 518 memset(&outputTlv,0, sizeof(outputTlv)); 519 } 520 return WIFI_SUCCESS; 521 } 522 523 int NanCommand::getNanBeaconSdfPayload(NanBeaconSdfPayloadInd *event) 524 { 525 if (event == NULL || mNanVendorEvent == NULL) { 526 ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p", 527 __func__, event, mNanVendorEvent); 528 return WIFI_ERROR_INVALID_ARGS; 529 } 530 531 pNanBeaconSdfPayloadIndMsg pRsp = (pNanBeaconSdfPayloadIndMsg)mNanVendorEvent; 532 memset(&event->data, 0, sizeof(event->data)); 533 534 u8 *pInputTlv = pRsp->ptlv; 535 NanTlv outputTlv; 536 u16 readLen = 0; 537 int remainingLen = (mNanDataLen - \ 538 (sizeof(NanMsgHeader))); 539 540 //Has Mac address 541 if (remainingLen <= 0) { 542 ALOGV("%s: No TLV's present",__func__); 543 return WIFI_SUCCESS; 544 } 545 546 ALOGV("%s: TLV remaining Len:%d",__func__, remainingLen); 547 while ((remainingLen > 0) && 548 (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) { 549 ALOGV("%s: Remaining Len:%d readLen:%d type:%d length:%d", 550 __func__, remainingLen, readLen, outputTlv.type, 551 outputTlv.length); 552 switch (outputTlv.type) { 553 case NAN_TLV_TYPE_MAC_ADDRESS: 554 if (outputTlv.length > sizeof(event->addr)) { 555 outputTlv.length = sizeof(event->addr); 556 } 557 memcpy(event->addr, outputTlv.value, 558 outputTlv.length); 559 break; 560 561 case NAN_TLV_TYPE_VENDOR_SPECIFIC_ATTRIBUTE_RECEIVE: 562 { 563 NanReceiveVendorSpecificAttribute* recvVsaattr = &event->vsa; 564 if (outputTlv.length < sizeof(u32)) { 565 ALOGE("NAN_TLV_TYPE_VENDOR_SPECIFIC_ATTRIBUTE_RECEIVE" 566 "Incorrect length:%d", outputTlv.length); 567 break; 568 } 569 event->is_vsa_received = 1; 570 recvVsaattr->vsa_received_on = (outputTlv.value[0] >> 1) & 0x07; 571 memcpy(&recvVsaattr->vendor_oui, &outputTlv.value[1], 572 3); 573 recvVsaattr->attr_len = outputTlv.length - 4; 574 if (recvVsaattr->attr_len > NAN_MAX_VSA_DATA_LEN) { 575 recvVsaattr->attr_len = NAN_MAX_VSA_DATA_LEN; 576 } 577 if (recvVsaattr->attr_len) { 578 memcpy(recvVsaattr->vsa, &outputTlv.value[4], 579 recvVsaattr->attr_len); 580 } 581 break; 582 } 583 584 case NAN_TLV_TYPE_BEACON_SDF_PAYLOAD_RECEIVE: 585 event->is_beacon_sdf_payload_received = 1; 586 event->data.frame_len = outputTlv.length; 587 if (event->data.frame_len > NAN_MAX_FRAME_DATA_LEN) { 588 event->data.frame_len = NAN_MAX_FRAME_DATA_LEN; 589 } 590 memcpy(&event->data.frame_data, &outputTlv.value[0], 591 event->data.frame_len); 592 break; 593 594 default: 595 ALOGV("Unhandled TLV Type:%d", outputTlv.type); 596 break; 597 } 598 remainingLen -= readLen; 599 pInputTlv += readLen; 600 memset(&outputTlv,0, sizeof(outputTlv)); 601 } 602 return WIFI_SUCCESS; 603 } 604 605 void NanCommand::getNanReceivePostConnectivityCapabilityVal( 606 const u8 *pInValue, 607 NanReceivePostConnectivityCapability *pRxCapab) 608 { 609 if (pInValue && pRxCapab) { 610 pRxCapab->is_mesh_supported = (pInValue[0] & (0x01 << 5)); 611 pRxCapab->is_ibss_supported = (pInValue[0] & (0x01 << 4)); 612 pRxCapab->wlan_infra_field = (pInValue[0] & (0x01 << 3)); 613 pRxCapab->is_tdls_supported = (pInValue[0] & (0x01 << 2)); 614 pRxCapab->is_wfds_supported = (pInValue[0] & (0x01 << 1)); 615 pRxCapab->is_wfd_supported = pInValue[0] & 0x01; 616 } 617 } 618 619 int NanCommand::getNanReceivePostDiscoveryVal(const u8 *pInValue, 620 u32 length, 621 NanReceivePostDiscovery *pRxDisc) 622 { 623 int ret = 0; 624 625 if (length <= 8 || pInValue == NULL) { 626 ALOGE("%s: Invalid Arg TLV Len %d < 4", 627 __func__, length); 628 return -1; 629 } 630 631 pRxDisc->type = (NanConnectionType) pInValue[0]; 632 pRxDisc->role = (NanDeviceRole) pInValue[1]; 633 pRxDisc->duration = (NanAvailDuration) (pInValue[2] & 0x03); 634 pRxDisc->mapid = ((pInValue[2] >> 2) & 0x0F); 635 memcpy(&pRxDisc->avail_interval_bitmap, 636 &pInValue[4], 637 sizeof(pRxDisc->avail_interval_bitmap)); 638 639 u8 *pInputTlv = (u8 *)&pInValue[8]; 640 NanTlv outputTlv; 641 u16 readLen = 0; 642 int remainingLen = (length - 8); 643 644 //Has Mac address 645 if (remainingLen <= 0) { 646 ALOGE("%s: No TLV's present",__func__); 647 return -1; 648 } 649 650 ALOGV("%s: TLV remaining Len:%d",__func__, remainingLen); 651 while ((remainingLen > 0) && 652 (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) { 653 ALOGV("%s: Remaining Len:%d readLen:%d type:%d length:%d", 654 __func__, remainingLen, readLen, outputTlv.type, 655 outputTlv.length); 656 switch (outputTlv.type) { 657 case NAN_TLV_TYPE_MAC_ADDRESS: 658 if (outputTlv.length > sizeof(pRxDisc->addr)) { 659 outputTlv.length = sizeof(pRxDisc->addr); 660 } 661 memcpy(pRxDisc->addr, outputTlv.value, outputTlv.length); 662 break; 663 case NAN_TLV_TYPE_WLAN_MESH_ID: 664 if (outputTlv.length > sizeof(pRxDisc->mesh_id)) { 665 outputTlv.length = sizeof(pRxDisc->mesh_id); 666 } 667 memcpy(pRxDisc->mesh_id, outputTlv.value, outputTlv.length); 668 pRxDisc->mesh_id_len = outputTlv.length; 669 break; 670 case NAN_TLV_TYPE_WLAN_INFRA_SSID: 671 if (outputTlv.length > sizeof(pRxDisc->infrastructure_ssid_val)) { 672 outputTlv.length = sizeof(pRxDisc->infrastructure_ssid_val); 673 } 674 memcpy(pRxDisc->infrastructure_ssid_val, outputTlv.value, 675 outputTlv.length); 676 pRxDisc->infrastructure_ssid_len = outputTlv.length; 677 default: 678 ALOGV("Unhandled TLV Type:%d", outputTlv.type); 679 break; 680 } 681 remainingLen -= readLen; 682 pInputTlv += readLen; 683 memset(&outputTlv,0, sizeof(outputTlv)); 684 } 685 return ret; 686 } 687 688 int NanCommand::getNanFurtherAvailabilityMap(const u8 *pInValue, 689 u32 length, 690 u8 *num_chans, 691 NanFurtherAvailabilityChannel *pFac) 692 { 693 int idx = 0; 694 695 if ((length == 0) || pInValue == NULL) { 696 ALOGE("%s: Invalid Arg TLV Len %d or pInValue NULL", 697 __func__, length); 698 return -1; 699 } 700 701 *num_chans = pInValue[0]; 702 if (*num_chans > NAN_MAX_FAM_CHANNELS) { 703 ALOGE("%s: Unable to accommodate numchans %d", 704 __func__, *num_chans); 705 return -1; 706 } 707 708 if (length < (sizeof(u8) + 709 (*num_chans * sizeof(NanFurtherAvailabilityChan)))) { 710 ALOGE("%s: Invalid TLV Length", __func__); 711 return -1; 712 } 713 714 for (idx = 0; idx < *num_chans; idx++) { 715 pNanFurtherAvailabilityChan pRsp = \ 716 (pNanFurtherAvailabilityChan)((u8 *)&pInValue[1] + \ 717 (idx * sizeof(NanFurtherAvailabilityChan))); 718 719 pFac->entry_control = \ 720 (NanAvailDuration)(pRsp->entryCtrl.availIntDuration); 721 pFac->mapid = pRsp->entryCtrl.mapId; 722 pFac->class_val = pRsp->opClass; 723 pFac->channel = pRsp->channel; 724 memcpy(&pFac->avail_interval_bitmap, 725 &pRsp->availIntBitmap, 726 sizeof(pFac->avail_interval_bitmap)); 727 pFac++; 728 } 729 return 0; 730 } 731 732 int NanCommand::getNanStaParameter(wifi_interface_handle iface, 733 NanStaParameter *pRsp) 734 { 735 int ret = WIFI_ERROR_NONE; 736 int res = -1; 737 int id = 1; 738 NanCommand *nanCommand = NULL; 739 interface_info *ifaceInfo = getIfaceInfo(iface); 740 wifi_handle wifiHandle = getWifiHandle(iface); 741 742 nanCommand = NanCommand::instance(wifiHandle); 743 if (nanCommand == NULL) { 744 ALOGE("%s: Error NanCommand NULL", __func__); 745 return WIFI_ERROR_UNKNOWN; 746 } 747 748 ret = nanCommand->create(); 749 if (ret < 0) 750 goto cleanup; 751 752 /* Set the interface Id of the message. */ 753 ret = nanCommand->set_iface_id(ifaceInfo->name); 754 if (ret < 0) 755 goto cleanup; 756 757 /* 758 Construct NL message to get the sync stats parameter 759 which has all the parameter required by staparameter. 760 */ 761 NanStatsRequest syncStats; 762 memset(&syncStats, 0, sizeof(syncStats)); 763 syncStats.stats_type = NAN_STATS_ID_DE_TIMING_SYNC; 764 syncStats.clear = 0; 765 766 mStaParam = pRsp; 767 ret = putNanStats(id, &syncStats); 768 if (ret != 0) { 769 ALOGE("%s: putNanStats Error:%d",__func__, ret); 770 goto cleanup; 771 } 772 ret = requestEvent(); 773 if (ret != 0) { 774 ALOGE("%s: requestEvent Error:%d",__func__, ret); 775 goto cleanup; 776 } 777 778 struct timespec abstime; 779 abstime.tv_sec = 4; 780 abstime.tv_nsec = 0; 781 res = mCondition.wait(abstime); 782 if (res == ETIMEDOUT) 783 { 784 ALOGE("%s: Time out happened.", __func__); 785 ret = WIFI_ERROR_TIMED_OUT; 786 goto cleanup; 787 } 788 ALOGV("%s: NanStaparameter Master_pref:%x," \ 789 " Random_factor:%x, hop_count:%x " \ 790 " beacon_transmit_time:%d", __func__, 791 pRsp->master_pref, pRsp->random_factor, 792 pRsp->hop_count, pRsp->beacon_transmit_time); 793 cleanup: 794 mStaParam = NULL; 795 return (int)ret; 796 } 797