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