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 "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