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 "nan.h"
     21 #include "wifi_hal.h"
     22 #include "nan_i.h"
     23 #include "nancommand.h"
     24 #include <errno.h>
     25 
     26 #define NAN_TERMINATED_BEGINNING_OFFSET       8192
     27 
     28 //Function which calls the necessaryIndication callback
     29 //based on the indication type
     30 int NanCommand::handleNanIndication()
     31 {
     32     //Based on the message_id in the header determine the Indication type
     33     //and call the necessary callback handler
     34     u16 msg_id;
     35     int res = 0;
     36 
     37     ALOGI("handleNanIndication called %p", this);
     38     msg_id = getIndicationType();
     39 
     40     ALOGI("handleNanIndication msg_id:%u", msg_id);
     41     switch (msg_id) {
     42     case NAN_INDICATION_PUBLISH_REPLIED:
     43         NanPublishRepliedInd publishRepliedInd;
     44         memset(&publishRepliedInd, 0, sizeof(publishRepliedInd));
     45         res = getNanPublishReplied(&publishRepliedInd);
     46         if (!res && mHandler.EventPublishReplied) {
     47             (*mHandler.EventPublishReplied)(&publishRepliedInd,
     48                                             mUserData);
     49         }
     50         break;
     51 
     52     case NAN_INDICATION_PUBLISH_TERMINATED:
     53         NanPublishTerminatedInd publishTerminatedInd;
     54         memset(&publishTerminatedInd, 0, sizeof(publishTerminatedInd));
     55         res = getNanPublishTerminated(&publishTerminatedInd);
     56         if (!res && mHandler.EventPublishTerminated) {
     57             (*mHandler.EventPublishTerminated)(&publishTerminatedInd,
     58                                                mUserData);
     59         }
     60         break;
     61 
     62     case NAN_INDICATION_MATCH:
     63         NanMatchInd matchInd;
     64         memset(&matchInd, 0, sizeof(matchInd));
     65         res = getNanMatch(&matchInd);
     66         if (!res && mHandler.EventMatch) {
     67             (*mHandler.EventMatch)(&matchInd, mUserData);
     68         }
     69         break;
     70 
     71     case NAN_INDICATION_UNMATCH:
     72         NanUnmatchInd unMatchInd;
     73         memset(&unMatchInd, 0, sizeof(unMatchInd));
     74         res = getNanUnMatch(&unMatchInd);
     75         if (!res && mHandler.EventUnMatch) {
     76             (*mHandler.EventUnMatch)(&unMatchInd, mUserData);
     77         }
     78         break;
     79 
     80     case NAN_INDICATION_SUBSCRIBE_TERMINATED:
     81         NanSubscribeTerminatedInd subscribeTerminatedInd;
     82         memset(&subscribeTerminatedInd, 0, sizeof(subscribeTerminatedInd));
     83         res = getNanSubscribeTerminated(&subscribeTerminatedInd);
     84         if (!res && mHandler.EventSubscribeTerminated) {
     85             (*mHandler.EventSubscribeTerminated)(&subscribeTerminatedInd,
     86                                                  mUserData);
     87         }
     88         break;
     89 
     90     case NAN_INDICATION_DE_EVENT:
     91         NanDiscEngEventInd discEngEventInd;
     92         memset(&discEngEventInd, 0, sizeof(discEngEventInd));
     93         res = getNanDiscEngEvent(&discEngEventInd);
     94         if (!res && mHandler.EventDiscEngEvent) {
     95             (*mHandler.EventDiscEngEvent)(&discEngEventInd,
     96                                           mUserData);
     97         }
     98         break;
     99 
    100     case NAN_INDICATION_FOLLOWUP:
    101         NanFollowupInd followupInd;
    102         memset(&followupInd, 0, sizeof(followupInd));
    103         res = getNanFollowup(&followupInd);
    104         if (!res && mHandler.EventFollowup) {
    105             (*mHandler.EventFollowup)(&followupInd,
    106                                       mUserData);
    107         }
    108         break;
    109 
    110     case NAN_INDICATION_DISABLED:
    111         NanDisabledInd disabledInd;
    112         memset(&disabledInd, 0, sizeof(disabledInd));
    113         res = getNanDisabled(&disabledInd);
    114         if (!res && mHandler.EventDisabled) {
    115             (*mHandler.EventDisabled)(&disabledInd,
    116                                       mUserData);
    117         }
    118         break;
    119 
    120     case NAN_INDICATION_TCA:
    121         NanTCAInd tcaInd;
    122         memset(&tcaInd, 0, sizeof(tcaInd));
    123         res = getNanTca(&tcaInd);
    124         if (!res && mHandler.EventTca) {
    125             (*mHandler.EventTca)(&tcaInd,
    126                                  mUserData);
    127         }
    128         break;
    129 
    130     case NAN_INDICATION_BEACON_SDF_PAYLOAD:
    131         NanBeaconSdfPayloadInd beaconSdfPayloadInd;
    132         memset(&beaconSdfPayloadInd, 0, sizeof(beaconSdfPayloadInd));
    133         res = getNanBeaconSdfPayload(&beaconSdfPayloadInd);
    134         if (!res && mHandler.EventSdfPayload) {
    135             (*mHandler.EventSdfPayload)(&beaconSdfPayloadInd,
    136                                         mUserData);
    137         }
    138         break;
    139 
    140     default:
    141         ALOGE("handleNanIndication error invalid msg_id:%u", msg_id);
    142         res = (int)WIFI_ERROR_INVALID_REQUEST_ID;
    143         break;
    144     }
    145     return res;
    146 }
    147 
    148 //Function which will return the Nan Indication type based on
    149 //the initial few bytes of mNanVendorEvent
    150 NanIndicationType NanCommand::getIndicationType()
    151 {
    152     if (mNanVendorEvent == NULL) {
    153         ALOGE("%s: Invalid argument mNanVendorEvent:%p",
    154               __func__, mNanVendorEvent);
    155         return NAN_INDICATION_UNKNOWN;
    156     }
    157 
    158     NanMsgHeader *pHeader = (NanMsgHeader *)mNanVendorEvent;
    159 
    160     switch (pHeader->msgId) {
    161     case NAN_MSG_ID_PUBLISH_REPLIED_IND:
    162         return NAN_INDICATION_PUBLISH_REPLIED;
    163     case NAN_MSG_ID_PUBLISH_TERMINATED_IND:
    164         return NAN_INDICATION_PUBLISH_TERMINATED;
    165     case NAN_MSG_ID_MATCH_IND:
    166         return NAN_INDICATION_MATCH;
    167     case NAN_MSG_ID_UNMATCH_IND:
    168         return NAN_INDICATION_UNMATCH;
    169     case NAN_MSG_ID_FOLLOWUP_IND:
    170         return NAN_INDICATION_FOLLOWUP;
    171     case NAN_MSG_ID_SUBSCRIBE_TERMINATED_IND:
    172         return NAN_INDICATION_SUBSCRIBE_TERMINATED;
    173     case  NAN_MSG_ID_DE_EVENT_IND:
    174         return NAN_INDICATION_DE_EVENT;
    175     case NAN_MSG_ID_DISABLE_IND:
    176         return NAN_INDICATION_DISABLED;
    177     case NAN_MSG_ID_TCA_IND:
    178         return NAN_INDICATION_TCA;
    179 #ifdef NAN_2_0
    180     case NAN_MSG_ID_BEACON_SDF_IND:
    181         return NAN_INDICATION_BEACON_SDF_PAYLOAD;
    182 #endif /* NAN_2_0 */
    183     default:
    184         return NAN_INDICATION_UNKNOWN;
    185     }
    186 }
    187 
    188 int NanCommand::getNanPublishReplied(NanPublishRepliedInd *event)
    189 {
    190     if (event == NULL || mNanVendorEvent == NULL) {
    191         ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
    192               __func__, event, mNanVendorEvent);
    193         return WIFI_ERROR_INVALID_ARGS;
    194     }
    195 
    196     pNanPublishRepliedIndMsg pRsp = (pNanPublishRepliedIndMsg)mNanVendorEvent;
    197     event->header.handle = pRsp->fwHeader.handle;
    198     event->header.transaction_id = pRsp->fwHeader.transactionId;
    199 #ifndef NAN_2_0
    200     memcpy(event->addr, pRsp->publishRepliedIndParams.macAddr, sizeof(event->addr));
    201 #else /* NAN_2_0 */
    202     event->rssi_value = 0;
    203     u8 *pInputTlv = pRsp->ptlv;
    204     NanTlv outputTlv;
    205     u16 readLen = 0;
    206     int ret = 0;
    207     int remainingLen = (mNanDataLen - \
    208         (sizeof(NanMsgHeader)));
    209 
    210     //Has NAN Mac address mandatory, received RSSI value optional
    211     //POST_NAN_CONNECTIVITY_CAPABILITIES_RECEIVE
    212     //POST_NAN_DISCOVERY_ATTRIBUTE_RECEIVE
    213     //NAN_FURTHER_AVAILABILITY_MAP
    214     //NAN_CLUSTER_ATTRIBUTE
    215     if (remainingLen <= 0) {
    216         ALOGI("%s: No TLV's present",__func__);
    217         return WIFI_SUCCESS;
    218     }
    219     ALOGI("%s: TLV remaining Len:%d",__func__, remainingLen);
    220     while ((remainingLen > 0) &&
    221            (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
    222         ALOGI("%s: Remaining Len:%d readLen:%d type:%d length:%d",
    223               __func__, remainingLen, readLen, outputTlv.type,
    224               outputTlv.length);
    225         switch (outputTlv.type) {
    226         case NAN_TLV_TYPE_MAC_ADDRESS:
    227             if (outputTlv.length > sizeof(event->addr)) {
    228                 outputTlv.length = sizeof(event->addr);
    229             }
    230             memcpy(event->addr, outputTlv.value, outputTlv.length);
    231             break;
    232         case NAN_TLV_TYPE_RECEIVED_RSSI_VALUE:
    233             if (outputTlv.length > sizeof(event->rssi_value)) {
    234                 outputTlv.length = sizeof(event->rssi_value);
    235             }
    236             memcpy(&event->rssi_value, outputTlv.value,
    237                    outputTlv.length);
    238             break;
    239         case NAN_TLV_TYPE_POST_NAN_CONNECTIVITY_CAPABILITIES_RECEIVE:
    240             if (outputTlv.length != sizeof(u32)) {
    241                 ALOGE("NAN_TLV_TYPE_POST_NAN_CONNECTIVITY_CAPABILITIES_RECEIVE"
    242                       "Incorrect size:%d expecting %d", outputTlv.length,
    243                       sizeof(u32));
    244                 break;
    245             }
    246             event->is_conn_capability_valid = 1;
    247             /* Populate conn_capability from received TLV */
    248             getNanReceivePostConnectivityCapabilityVal(outputTlv.value,
    249                                                        &event->conn_capability);
    250             break;
    251         case NAN_TLV_TYPE_POST_NAN_DISCOVERY_ATTRIBUTE_RECEIVE:
    252             /* Populate receive discovery attribute from
    253                received TLV */
    254             ret = getNanReceivePostDiscoveryVal(outputTlv.value,
    255                                                     outputTlv.length,
    256                                                     &event->discovery_attr);
    257             if (ret == 0) {
    258                 event->is_discovery_attr_valid = 1;
    259             }
    260             else {
    261                 ALOGE("NAN_TLV_TYPE_POST_NAN_DISCOVERY_ATTRIBUTE_RECEIVE"
    262                       "Incorrect");
    263             }
    264             break;
    265         case NAN_TLV_TYPE_FURTHER_AVAILABILITY_MAP:
    266             /* Populate further availability bitmap from
    267                received TLV */
    268             ret = getNanFurtherAvailabilityMap(outputTlv.value,
    269                                                outputTlv.length,
    270                                                &event->fam);
    271             if (ret == 0) {
    272                 event->is_fam_valid = 1;
    273             }
    274             else {
    275                 ALOGE("NAN_TLV_TYPE_FURTHER_AVAILABILITY_MAP"
    276                       "Incorrect");
    277             }
    278             break;
    279         case NAN_TLV_TYPE_CLUSTER_ATTIBUTE:
    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             ALOGI("Unknown TLV type skipped");
    289             break;
    290         }
    291         remainingLen -= readLen;
    292         pInputTlv += readLen;
    293         memset(&outputTlv, 0, sizeof(outputTlv));
    294     }
    295 #endif /* NAN_2_0 */
    296     return WIFI_SUCCESS;
    297 }
    298 
    299 
    300 int NanCommand::getNanPublishTerminated(NanPublishTerminatedInd *event)
    301 {
    302     if (event == NULL || mNanVendorEvent == NULL) {
    303         ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
    304               __func__, event, mNanVendorEvent);
    305         return WIFI_ERROR_INVALID_ARGS;
    306     }
    307 
    308     pNanPublishTerminatedIndMsg pRsp = (pNanPublishTerminatedIndMsg)mNanVendorEvent;
    309     event->header.handle = pRsp->fwHeader.handle;
    310     event->header.transaction_id = pRsp->fwHeader.transactionId;
    311 #ifdef NAN_2_0
    312     pRsp->reason -= NAN_TERMINATED_BEGINNING_OFFSET;
    313 #endif /* NAN_2_0 */
    314     event->reason = (NanTerminatedStatus)pRsp->reason;
    315     return WIFI_SUCCESS;
    316 }
    317 
    318 int NanCommand::getNanMatch(NanMatchInd *event)
    319 {
    320     if (event == NULL || mNanVendorEvent == NULL) {
    321         ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
    322               __func__, event, mNanVendorEvent);
    323         return WIFI_ERROR_INVALID_ARGS;
    324     }
    325 
    326     pNanMatchIndMsg pRsp = (pNanMatchIndMsg)mNanVendorEvent;
    327     event->header.handle = pRsp->fwHeader.handle;
    328     event->header.transaction_id = pRsp->fwHeader.transactionId;
    329     event->match_handle = pRsp->matchIndParams.matchHandle;
    330 #ifndef NAN_2_0
    331     memcpy(event->addr, pRsp->matchIndParams.macAddr, sizeof(event->addr));
    332 #else /* NAN_2_0 */
    333     event->match_occured_flag = pRsp->matchIndParams.matchOccuredFlag;
    334     event->out_of_resource_flag = pRsp->matchIndParams.outOfResourceFlag;
    335 #endif /* NAN_2_0 */
    336 
    337     u8 *pInputTlv = pRsp->ptlv;
    338     NanTlv outputTlv;
    339     u16 readLen = 0;
    340     int remainingLen = (mNanDataLen - \
    341         (sizeof(NanMsgHeader) + sizeof(NanMatchIndParams)));
    342     int ret = 0;
    343 
    344     //Has SDF match filter and service specific info TLV
    345     if (remainingLen <= 0) {
    346         ALOGI("%s: No TLV's present",__func__);
    347         return WIFI_SUCCESS;
    348     }
    349     ALOGI("%s: TLV remaining Len:%d",__func__, remainingLen);
    350     while ((remainingLen > 0) &&
    351            (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
    352         ALOGI("%s: Remaining Len:%d readLen:%d type:%d length:%d",
    353               __func__, remainingLen, readLen, outputTlv.type,
    354               outputTlv.length);
    355         switch (outputTlv.type) {
    356         case NAN_TLV_TYPE_SERVICE_SPECIFIC_INFO:
    357             if (outputTlv.length > NAN_MAX_SERVICE_NAME_LEN) {
    358                 outputTlv.length = NAN_MAX_SERVICE_NAME_LEN;
    359             }
    360             event->service_specific_info_len = outputTlv.length;
    361             memcpy(event->service_specific_info, outputTlv.value,
    362                    outputTlv.length);
    363             break;
    364         case NAN_TLV_TYPE_SDF_MATCH_FILTER:
    365             if (outputTlv.length > NAN_MAX_MATCH_FILTER_LEN) {
    366                 outputTlv.length = NAN_MAX_MATCH_FILTER_LEN;
    367             }
    368             event->sdf_match_filter_len = outputTlv.length;
    369             memcpy(event->sdf_match_filter, outputTlv.value,
    370                    outputTlv.length);
    371             break;
    372 #ifdef NAN_2_0
    373         case NAN_TLV_TYPE_MAC_ADDRESS:
    374             if (outputTlv.length > sizeof(event->addr)) {
    375                 outputTlv.length = sizeof(event->addr);
    376             }
    377             memcpy(event->addr, outputTlv.value, outputTlv.length);
    378             break;
    379         case NAN_TLV_TYPE_RECEIVED_RSSI_VALUE:
    380             if (outputTlv.length > sizeof(event->rssi_value)) {
    381                 outputTlv.length = sizeof(event->rssi_value);
    382             }
    383             memcpy(&event->rssi_value, outputTlv.value,
    384                    outputTlv.length);
    385             break;
    386         case NAN_TLV_TYPE_POST_NAN_CONNECTIVITY_CAPABILITIES_RECEIVE:
    387             if (outputTlv.length != sizeof(u32)) {
    388                 ALOGE("NAN_TLV_TYPE_POST_NAN_CONNECTIVITY_CAPABILITIES_RECEIVE"
    389                       "Incorrect size:%d expecting %d", outputTlv.length,
    390                       sizeof(u32));
    391                 break;
    392             }
    393             event->is_conn_capability_valid = 1;
    394             /* Populate conn_capability from received TLV */
    395             getNanReceivePostConnectivityCapabilityVal(outputTlv.value,
    396                                                        &event->conn_capability);
    397             break;
    398         case NAN_TLV_TYPE_POST_NAN_DISCOVERY_ATTRIBUTE_RECEIVE:
    399             /* Populate receive discovery attribute from
    400                received TLV */
    401             ret = getNanReceivePostDiscoveryVal(outputTlv.value,
    402                                                     outputTlv.length,
    403                                                     &event->discovery_attr);
    404             if (ret == 0) {
    405                 event->is_discovery_attr_valid = 1;
    406             }
    407             else {
    408                 ALOGE("NAN_TLV_TYPE_POST_NAN_DISCOVERY_ATTRIBUTE_RECEIVE"
    409                       "Incorrect");
    410             }
    411             break;
    412         case NAN_TLV_TYPE_FURTHER_AVAILABILITY_MAP:
    413             /* Populate further availability bitmap from
    414                received TLV */
    415             ret = getNanFurtherAvailabilityMap(outputTlv.value,
    416                                                outputTlv.length,
    417                                                &event->fam);
    418             if (ret == 0) {
    419                 event->is_fam_valid = 1;
    420             }
    421             else {
    422                 ALOGE("NAN_TLV_TYPE_FURTHER_AVAILABILITY_MAP"
    423                       "Incorrect");
    424             }
    425             break;
    426         case NAN_TLV_TYPE_CLUSTER_ATTIBUTE:
    427             if (outputTlv.length > sizeof(event->cluster_attribute)) {
    428                 outputTlv.length = sizeof(event->cluster_attribute);
    429             }
    430             memcpy(event->cluster_attribute,
    431                    outputTlv.value, outputTlv.length);
    432             event->cluster_attribute_len = outputTlv.length;
    433             break;
    434 #endif /* NAN_2_0 */
    435         default:
    436             ALOGI("Unknown TLV type skipped");
    437             break;
    438         }
    439         remainingLen -= readLen;
    440         pInputTlv += readLen;
    441         memset(&outputTlv, 0, sizeof(outputTlv));
    442     }
    443     return WIFI_SUCCESS;
    444 }
    445 
    446 int NanCommand::getNanUnMatch(NanUnmatchInd *event)
    447 {
    448     if (event == NULL || mNanVendorEvent == NULL) {
    449         ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
    450               __func__, event, mNanVendorEvent);
    451         return WIFI_ERROR_INVALID_ARGS;
    452     }
    453 
    454     pNanUnmatchIndMsg pRsp = (pNanUnmatchIndMsg)mNanVendorEvent;
    455     event->header.handle = pRsp->fwHeader.handle;
    456     event->header.transaction_id = pRsp->fwHeader.transactionId;
    457     event->match_handle = pRsp->unmatchIndParams.matchHandle;
    458     return WIFI_SUCCESS;
    459 }
    460 
    461 int NanCommand::getNanSubscribeTerminated(NanSubscribeTerminatedInd *event)
    462 {
    463     if (event == NULL || mNanVendorEvent == NULL) {
    464         ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
    465               __func__, event, mNanVendorEvent);
    466         return WIFI_ERROR_INVALID_ARGS;
    467     }
    468 
    469     pNanSubscribeTerminatedIndMsg pRsp = (pNanSubscribeTerminatedIndMsg)mNanVendorEvent;
    470     event->header.handle = pRsp->fwHeader.handle;
    471     event->header.transaction_id = pRsp->fwHeader.transactionId;
    472 #ifdef NAN_2_0
    473     pRsp->reason -= NAN_TERMINATED_BEGINNING_OFFSET;
    474 #endif /* NAN_2_0 */
    475     event->reason = (NanTerminatedStatus)pRsp->reason;
    476     return WIFI_SUCCESS;
    477 }
    478 
    479 int NanCommand::getNanFollowup(NanFollowupInd *event)
    480 {
    481     if (event == NULL || mNanVendorEvent == NULL) {
    482         ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
    483               __func__, event, mNanVendorEvent);
    484         return WIFI_ERROR_INVALID_ARGS;
    485     }
    486 
    487     pNanFollowupIndMsg pRsp = (pNanFollowupIndMsg)mNanVendorEvent;
    488     event->header.handle = pRsp->fwHeader.handle;
    489     event->header.transaction_id = pRsp->fwHeader.transactionId;
    490 #ifndef NAN_2_0
    491     memcpy(event->addr, pRsp->followupIndParams.macAddr, sizeof(event->addr));
    492 #else /* NAN_2_0*/
    493     event->match_handle = pRsp->followupIndParams.matchHandle;
    494 #endif
    495     event->dw_or_faw = pRsp->followupIndParams.window;
    496 
    497     u8 *pInputTlv = pRsp->ptlv;
    498     NanTlv outputTlv;
    499     u16 readLen = 0;
    500     int remainingLen = (mNanDataLen -  \
    501         (sizeof(NanMsgHeader) + sizeof(NanFollowupIndParams)));
    502 
    503     //Has service specific info and extended service specific info TLV
    504     if (remainingLen <= 0) {
    505         ALOGI("%s: No TLV's present",__func__);
    506         return WIFI_SUCCESS;
    507     }
    508     ALOGI("%s: TLV remaining Len:%d",__func__, remainingLen);
    509     while ((remainingLen > 0) &&
    510            (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
    511         ALOGI("%s: Remaining Len:%d readLen:%d type:%d length:%d",
    512               __func__, remainingLen, readLen, outputTlv.type,
    513               outputTlv.length);
    514         switch (outputTlv.type) {
    515         case NAN_TLV_TYPE_SERVICE_SPECIFIC_INFO:
    516         case NAN_TLV_TYPE_EXT_SERVICE_SPECIFIC_INFO:
    517             if (outputTlv.length > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) {
    518                 outputTlv.length = NAN_MAX_SERVICE_SPECIFIC_INFO_LEN;
    519             }
    520             event->service_specific_info_len = outputTlv.length;
    521             memcpy(event->service_specific_info, outputTlv.value,
    522                    outputTlv.length);
    523             break;
    524 #ifdef NAN_2_0
    525         case NAN_TLV_TYPE_MAC_ADDRESS:
    526             if (outputTlv.length > sizeof(event->addr)) {
    527                 outputTlv.length = sizeof(event->addr);
    528             }
    529             memcpy(event->addr, outputTlv.value, outputTlv.length);
    530             break;
    531 #endif /* NAN_2_0 */
    532         default:
    533             ALOGI("Unknown TLV type skipped");
    534             break;
    535         }
    536         remainingLen -= readLen;
    537         pInputTlv += readLen;
    538         memset(&outputTlv, 0, sizeof(outputTlv));
    539     }
    540     return WIFI_SUCCESS;
    541 }
    542 
    543 int NanCommand::getNanDiscEngEvent(NanDiscEngEventInd *event)
    544 {
    545     if (event == NULL || mNanVendorEvent == NULL) {
    546         ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
    547               __func__, event, mNanVendorEvent);
    548         return WIFI_ERROR_INVALID_ARGS;
    549     }
    550 
    551     pNanEventIndMsg pRsp = (pNanEventIndMsg)mNanVendorEvent;
    552     event->header.handle = pRsp->fwHeader.handle;
    553     event->header.transaction_id = pRsp->fwHeader.transactionId;
    554 #ifndef NAN_2_0
    555     event->event_id = (NanEventId)pRsp->eventIndParams.eventId;
    556 #endif /* NAN_2_0 */
    557     memset(&event->data, 0, sizeof(event->data));
    558 
    559     u8 *pInputTlv = pRsp->ptlv;
    560     NanTlv outputTlv;
    561     u16 readLen = 0;
    562 #ifndef NAN_2_0
    563     int remainingLen = (mNanDataLen -  \
    564         (sizeof(NanMsgHeader) + sizeof(NanEventIndParams)));
    565 #else /* NAN_2_0 */
    566     int remainingLen = (mNanDataLen -  \
    567         (sizeof(NanMsgHeader)));
    568 #endif /* NAN_2_0 */
    569 
    570     //Has Self-STA Mac TLV
    571     if (remainingLen <= 0) {
    572         ALOGI("%s: No TLV's present",__func__);
    573         return WIFI_SUCCESS;
    574     }
    575 
    576     ALOGI("%s: TLV remaining Len:%d event_id:%d",__func__,
    577           remainingLen, event->event_id);
    578     while ((remainingLen > 0) &&
    579            (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
    580         ALOGI("%s: Remaining Len:%d readLen:%d type:%d length:%d",
    581               __func__, remainingLen, readLen, outputTlv.type,
    582               outputTlv.length);
    583 #ifdef NAN_2_0
    584         event->event_id = (NanEventId)outputTlv.type;
    585 #endif /* NAN_2_0 */
    586         //Here we should check on the event_id
    587         switch (event->event_id) {
    588         case NAN_EVENT_ID_STA_MAC_ADDR:
    589             if (outputTlv.length > NAN_MAC_ADDR_LEN) {
    590                 ALOGI("%s: Reading only first %d bytes of TLV",
    591                       __func__, NAN_MAC_ADDR_LEN);
    592                 outputTlv.length = NAN_MAC_ADDR_LEN;
    593             }
    594             memcpy(event->data.mac_addr.addr, outputTlv.value,
    595                    outputTlv.length);
    596             break;
    597         case NAN_EVENT_ID_STARTED_CLUSTER:
    598         case NAN_EVENT_ID_JOINED_CLUSTER:
    599             if (outputTlv.length > NAN_MAC_ADDR_LEN) {
    600                 ALOGI("%s: Reading only first %d bytes of TLV",
    601                       __func__, NAN_MAC_ADDR_LEN);
    602                 outputTlv.length = NAN_MAC_ADDR_LEN;
    603             }
    604             memcpy(event->data.cluster.addr, outputTlv.value,
    605                    outputTlv.length);
    606             break;
    607         default:
    608             ALOGI("Unhandled eventId:%d", event->event_id);
    609             break;
    610         }
    611         remainingLen -= readLen;
    612         pInputTlv += readLen;
    613         memset(&outputTlv,0, sizeof(outputTlv));
    614     }
    615     return WIFI_SUCCESS;
    616 }
    617 
    618 int NanCommand::getNanDisabled(NanDisabledInd *event)
    619 {
    620     if (event == NULL || mNanVendorEvent == NULL) {
    621         ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
    622               __func__, event, mNanVendorEvent);
    623         return WIFI_ERROR_INVALID_ARGS;
    624     }
    625 
    626     pNanDisableIndMsg pRsp = (pNanDisableIndMsg)mNanVendorEvent;
    627     event->header.handle = pRsp->fwHeader.handle;
    628     event->header.transaction_id = pRsp->fwHeader.transactionId;
    629     event->reason = (NanStatusType)pRsp->reason;
    630     return WIFI_SUCCESS;
    631 
    632 }
    633 
    634 int NanCommand::getNanTca(NanTCAInd *event)
    635 {
    636     if (event == NULL || mNanVendorEvent == NULL) {
    637         ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
    638               __func__, event, mNanVendorEvent);
    639         return WIFI_ERROR_INVALID_ARGS;
    640     }
    641 
    642     pNanTcaIndMsg pRsp = (pNanTcaIndMsg)mNanVendorEvent;
    643     event->header.handle = pRsp->fwHeader.handle;
    644     event->header.transaction_id = pRsp->fwHeader.transactionId;
    645     memset(&event->data, 0, sizeof(event->data));
    646 #ifndef NAN_2_0
    647     event->tca_id = (NanTcaId)pRsp->tcaIndParams.tcaId;
    648 #else /* NAN_2_0 */
    649     event->tca_id = (NanTcaId)0;
    650 #endif /* NAN_2_0 */
    651 
    652     u8 *pInputTlv = pRsp->ptlv;
    653     NanTlv outputTlv;
    654     u16 readLen = 0;
    655 #ifndef NAN_2_0
    656     int remainingLen = (mNanDataLen -  \
    657         (sizeof(NanMsgHeader) + sizeof(NanTcaIndParams)));
    658 #else
    659     int remainingLen = (mNanDataLen -  \
    660         (sizeof(NanMsgHeader)));
    661 #endif
    662 
    663     //Has NAN_TCA_ID_CLUSTER_SIZE
    664     if (remainingLen <= 0) {
    665         ALOGI("%s: No TLV's present",__func__);
    666         return WIFI_SUCCESS;
    667     }
    668 
    669     ALOGI("%s: TLV remaining Len:%d tca_id:%d",__func__,
    670           remainingLen, event->tca_id);
    671     while ((remainingLen > 0) &&
    672            (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
    673         ALOGI("%s: Remaining Len:%d readLen:%d type:%d length:%d",
    674               __func__, remainingLen, readLen, outputTlv.type,
    675               outputTlv.length);
    676         //Here we should check on the event_id
    677         switch (event->tca_id) {
    678         case NAN_TCA_ID_CLUSTER_SIZE:
    679 #ifndef NAN_2_0
    680             if (outputTlv.length > sizeof(event->data.cluster.cluster_size)) {
    681                 outputTlv.length = sizeof(event->data.cluster.cluster_size);
    682             }
    683             memcpy(&(event->data.cluster.cluster_size), outputTlv.value,
    684                    outputTlv.length);
    685 #else /* NAN_2_0 */
    686             if (outputTlv.length != 2 * sizeof(u32)) {
    687                 ALOGE("%s: Wrong length %d in Tca Indication expecting %d bytes",
    688                       __func__, outputTlv.length, 2 * sizeof(u32));
    689                 break;
    690             }
    691             event->rising_direction_evt_flag = outputTlv.value[0] & 0x01;
    692             event->falling_direction_evt_flag = (outputTlv.value[0] & 0x02) >> 1;
    693             memcpy(&(event->data.cluster.cluster_size), &outputTlv.value[4],
    694                    sizeof(event->data.cluster.cluster_size));
    695 #endif /* NAN_2_0 */
    696             break;
    697         default:
    698             ALOGI("Unhandled eventId:%d", event->tca_id);
    699             break;
    700         }
    701         remainingLen -= readLen;
    702         pInputTlv += readLen;
    703         memset(&outputTlv,0, sizeof(outputTlv));
    704     }
    705     return WIFI_SUCCESS;
    706 }
    707 
    708 int NanCommand::getNanBeaconSdfPayload(NanBeaconSdfPayloadInd *event)
    709 {
    710     if (event == NULL || mNanVendorEvent == NULL) {
    711         ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
    712               __func__, event, mNanVendorEvent);
    713         return WIFI_ERROR_INVALID_ARGS;
    714     }
    715 
    716 #ifdef NAN_2_0
    717     pNanBeaconSdfPayloadIndMsg pRsp = (pNanBeaconSdfPayloadIndMsg)mNanVendorEvent;
    718     event->header.handle = pRsp->fwHeader.handle;
    719     event->header.transaction_id = pRsp->fwHeader.transactionId;
    720     memset(&event->data, 0, sizeof(event->data));
    721 
    722     u8 *pInputTlv = pRsp->ptlv;
    723     NanTlv outputTlv;
    724     u16 readLen = 0;
    725     int remainingLen = (mNanDataLen -  \
    726         (sizeof(NanMsgHeader)));
    727 
    728     //Has Mac address
    729     if (remainingLen <= 0) {
    730         ALOGI("%s: No TLV's present",__func__);
    731         return WIFI_SUCCESS;
    732     }
    733 
    734     ALOGI("%s: TLV remaining Len:%d",__func__, remainingLen);
    735     while ((remainingLen > 0) &&
    736            (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
    737         ALOGI("%s: Remaining Len:%d readLen:%d type:%d length:%d",
    738               __func__, remainingLen, readLen, outputTlv.type,
    739               outputTlv.length);
    740         //Here we should check on the event_id
    741         switch (outputTlv.type) {
    742         case NAN_TLV_TYPE_SELF_MAC_ADDR:
    743             if (outputTlv.length > sizeof(event->addr)) {
    744                 outputTlv.length = sizeof(event->addr);
    745             }
    746             memcpy(event->addr, outputTlv.value,
    747                    outputTlv.length);
    748             break;
    749 
    750         case NAN_TLV_TYPE_VENDOR_SPECIFIC_ATTRIBUTE_RECEIVE:
    751         {
    752             NanReceiveVendorSpecificAttribute* recvVsaattr = &event->vsa;
    753             if (outputTlv.length < sizeof(u32)) {
    754                 ALOGE("NAN_TLV_TYPE_VENDOR_SPECIFIC_ATTRIBUTE_RECEIVE"
    755                       "Incorrect length:%d", outputTlv.length);
    756                 break;
    757             }
    758             event->is_vsa_received = 1;
    759             recvVsaattr->vsa_received_on = (outputTlv.value[0] >> 1) & 0x07;
    760             memcpy(&recvVsaattr->vendor_oui, &outputTlv.value[1],
    761                    3);
    762             recvVsaattr->attr_len = outputTlv.length - 4;
    763             if (recvVsaattr->attr_len > NAN_MAX_VSA_DATA_LEN) {
    764                 recvVsaattr->attr_len = NAN_MAX_VSA_DATA_LEN;
    765             }
    766             if (recvVsaattr->attr_len) {
    767                 memcpy(recvVsaattr->vsa, &outputTlv.value[4],
    768                        recvVsaattr->attr_len);
    769             }
    770             break;
    771         }
    772 
    773         case NAN_TLV_TYPE_BEACON_SDF_PAYLOAD_RECEIVE:
    774             event->is_beacon_sdf_payload_received = 1;
    775             event->data.frame_len = outputTlv.length;
    776             if (event->data.frame_len > NAN_MAX_VSA_DATA_LEN) {
    777                 event->data.frame_len = NAN_MAX_VSA_DATA_LEN;
    778             }
    779             memcpy(&event->data.frame_data, &outputTlv.value[0],
    780                    event->data.frame_len);
    781             break;
    782 
    783         default:
    784             ALOGI("Unhandled TLV Type:%d", outputTlv.type);
    785             break;
    786         }
    787         remainingLen -= readLen;
    788         pInputTlv += readLen;
    789         memset(&outputTlv,0, sizeof(outputTlv));
    790     }
    791     return WIFI_SUCCESS;
    792 #else /* NAN_2_0 */
    793     return WIFI_ERROR_INVALID_ARGS;
    794 #endif /* NAN_2_0 */
    795 }
    796 
    797 void NanCommand::getNanReceivePostConnectivityCapabilityVal(
    798     const u8 *pInValue,
    799     NanReceivePostConnectivityCapability *pRxCapab)
    800 {
    801     if (pInValue && pRxCapab) {
    802         pRxCapab->is_mesh_supported = (pInValue[0] && (0x01 << 5));
    803         pRxCapab->is_ibss_supported = (pInValue[0] && (0x01 << 4));
    804         pRxCapab->wlan_infra_field = (pInValue[0] && (0x01 << 3));
    805         pRxCapab->is_tdls_supported = (pInValue[0] && (0x01 << 2));
    806         pRxCapab->is_wfds_supported = (pInValue[0] && (0x01 << 1));
    807         pRxCapab->is_wfd_supported = pInValue[0] && 0x01;
    808     }
    809 }
    810 
    811 int NanCommand::getNanReceivePostDiscoveryVal(const u8 *pInValue,
    812                                               u32 length,
    813                                               NanReceivePostDiscovery *pRxDisc)
    814 {
    815     int ret = 0;
    816 
    817 #ifdef NAN_2_0
    818     if (length <= 8 || pInValue == NULL) {
    819         ALOGE("%s: Invalid Arg TLV Len %d < 4",
    820               __func__, length);
    821         return -1;
    822     }
    823 
    824     pRxDisc->type = (NanConnectionType) pInValue[0];
    825     pRxDisc->role = (NanDeviceRole) pInValue[1];
    826     pRxDisc->duration = (NanAvailDuration) (pInValue[2] & 0x03);
    827     pRxDisc->mapid = ((pInValue[2] >> 2) & 0x0F);
    828     memcpy(&pRxDisc->avail_interval_bitmap,
    829            &pInValue[4],
    830            sizeof(pRxDisc->avail_interval_bitmap));
    831 
    832     u8 *pInputTlv = (u8 *)&pInValue[8];
    833     NanTlv outputTlv;
    834     u16 readLen = 0;
    835     int remainingLen = (length - 8);
    836 
    837     //Has Mac address
    838     if (remainingLen <= 0) {
    839         ALOGE("%s: No TLV's present",__func__);
    840         return -1;
    841     }
    842 
    843     ALOGI("%s: TLV remaining Len:%d",__func__, remainingLen);
    844     while ((remainingLen > 0) &&
    845            (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
    846         ALOGI("%s: Remaining Len:%d readLen:%d type:%d length:%d",
    847               __func__, remainingLen, readLen, outputTlv.type,
    848               outputTlv.length);
    849         switch (outputTlv.type) {
    850         case NAN_TLV_TYPE_MAC_ADDRESS:
    851             if (outputTlv.length > sizeof(pRxDisc->addr)) {
    852                 outputTlv.length = sizeof(pRxDisc->addr);
    853             }
    854             memcpy(pRxDisc->addr, outputTlv.value, outputTlv.length);
    855             break;
    856         case NAN_TLV_TYPE_WLAN_MESH_ID:
    857             if (outputTlv.length > sizeof(pRxDisc->mesh_id)) {
    858                 outputTlv.length = sizeof(pRxDisc->mesh_id);
    859             }
    860             memcpy(pRxDisc->mesh_id, outputTlv.value, outputTlv.length);
    861             pRxDisc->mesh_id_len = outputTlv.length;
    862             break;
    863         case NAN_TLV_TYPE_WLAN_INFRASTRUCTURE_SSID:
    864             if (outputTlv.length > sizeof(pRxDisc->infrastructure_ssid_val)) {
    865                 outputTlv.length = sizeof(pRxDisc->infrastructure_ssid_val);
    866             }
    867             memcpy(pRxDisc->infrastructure_ssid_val, outputTlv.value,
    868                    outputTlv.length);
    869             pRxDisc->infrastructure_ssid_len = outputTlv.length;
    870         default:
    871             ALOGI("Unhandled TLV Type:%d", outputTlv.type);
    872             break;
    873         }
    874         remainingLen -= readLen;
    875         pInputTlv += readLen;
    876         memset(&outputTlv,0, sizeof(outputTlv));
    877     }
    878 #endif /* NAN_2_0 */
    879     return ret;
    880 }
    881 
    882 int NanCommand::getNanFurtherAvailabilityMap(const u8 *pInValue,
    883                                              u32 length,
    884                                              NanFurtherAvailabilityMap *pFam)
    885 {
    886 #ifdef NAN_2_0
    887     int idx = 0;
    888 
    889     if ((length == 0) || pInValue == NULL) {
    890         ALOGE("%s: Invalid Arg TLV Len %d or pInValue NULL",
    891               __func__, length);
    892         return -1;
    893     }
    894 
    895     pFam->numchans = pInValue[0];
    896     if (pFam->numchans > NAN_MAX_FAM_CHANNELS) {
    897         ALOGE("%s: Unable to accommodate numchans %d",
    898               __func__, pFam->numchans);
    899         return -1;
    900     }
    901     for (idx = 0; idx < pFam->numchans; idx++) {
    902         pNanFurtherAvailabilityChan pRsp = \
    903               (pNanFurtherAvailabilityChan)(pInValue[1] + \
    904               (idx * sizeof(NanFurtherAvailabilityChan)));
    905         NanFurtherAvailabilityChannel *pFamChan = &pFam->famchan[idx];
    906 
    907         pFamChan->entry_control = \
    908             (NanAvailDuration)(pRsp->entryCtrl.availIntDuration);
    909         pFamChan->mapid = pRsp->entryCtrl.mapId;
    910         pFamChan->class_val = pRsp->opClass;
    911         pFamChan->channel = pRsp->channel;
    912         memcpy(&pFamChan->avail_interval_bitmap,
    913                &pRsp->availIntBitmap,
    914                sizeof(pFamChan->avail_interval_bitmap));
    915     }
    916 #endif /* NAN_2_0*/
    917     return 0;
    918 }
    919 
    920 int NanCommand::getNanStaParameter(NanStaParameter *pRsp)
    921 {
    922     int ret = WIFI_ERROR_NONE;
    923     int res = -1;
    924 
    925     /*
    926        Construct NL message to get the sync stats parameter
    927        which has all the parameter required by staparameter.
    928     */
    929     NanStatsRequest syncStats;
    930     memset(&syncStats, 0, sizeof(syncStats));
    931     syncStats.header.handle = 0x0;
    932     syncStats.header.transaction_id = 0x1234;
    933     syncStats.stats_id = NAN_STATS_ID_DE_TIMING_SYNC;
    934     syncStats.clear = 0;
    935 
    936     mStaParam = pRsp;
    937     ret = putNanStats(&syncStats);
    938     if (ret != 0) {
    939         ALOGE("%s: putNanStats Error:%d",__func__, ret);
    940         goto cleanup;
    941     }
    942     ret = requestEvent();
    943     if (ret != 0) {
    944         ALOGE("%s: requestEvent Error:%d",__func__, ret);
    945         goto cleanup;
    946     }
    947 
    948     struct timespec abstime;
    949     abstime.tv_sec = 4;
    950     abstime.tv_nsec = 0;
    951     res = mCondition.wait(abstime);
    952     if (res == ETIMEDOUT)
    953     {
    954         ALOGE("%s: Time out happened.", __func__);
    955         ret = WIFI_ERROR_TIMED_OUT;
    956         goto cleanup;
    957     }
    958     ALOGI("%s: NanStaparameter Master_pref:%x," \
    959           " Random_factor:%x, hop_count:%x " \
    960           " beacon_transmit_time:%d", __func__,
    961           pRsp->master_pref, pRsp->random_factor,
    962           pRsp->hop_count, pRsp->beacon_transmit_time);
    963 cleanup:
    964     mStaParam = NULL;
    965     return (int)ret;
    966 }
    967