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 "wifi_hal.h"
     20 #include "nan_i.h"
     21 #include "nancommand.h"
     22 
     23 int NanCommand::putNanEnable(transaction_id id, const NanEnableRequest *pReq)
     24 {
     25     ALOGV("NAN_ENABLE");
     26     size_t message_len = NAN_MAX_ENABLE_REQ_SIZE;
     27 
     28     if (pReq == NULL) {
     29         cleanup();
     30         return WIFI_ERROR_INVALID_ARGS;
     31     }
     32 
     33     message_len += \
     34         (
     35           pReq->config_support_5g ? (SIZEOF_TLV_HDR + \
     36           sizeof(pReq->support_5g_val)) : 0 \
     37         ) + \
     38         (
     39           pReq->config_sid_beacon ? (SIZEOF_TLV_HDR + \
     40           sizeof(pReq->sid_beacon_val)) : 0 \
     41         ) + \
     42         (
     43           pReq->config_2dot4g_rssi_close ? (SIZEOF_TLV_HDR + \
     44           sizeof(pReq->rssi_close_2dot4g_val)) : 0 \
     45         ) + \
     46         (
     47           pReq->config_2dot4g_rssi_middle ? (SIZEOF_TLV_HDR + \
     48           sizeof(pReq->rssi_middle_2dot4g_val)) : 0 \
     49         ) + \
     50         (
     51           pReq->config_hop_count_limit ? (SIZEOF_TLV_HDR + \
     52           sizeof(pReq->hop_count_limit_val)) : 0 \
     53         ) + \
     54         (
     55           pReq->config_2dot4g_support ? (SIZEOF_TLV_HDR + \
     56           sizeof(pReq->support_2dot4g_val)) : 0 \
     57         ) + \
     58         (
     59           pReq->config_2dot4g_beacons ? (SIZEOF_TLV_HDR + \
     60           sizeof(pReq->beacon_2dot4g_val)) : 0 \
     61         ) + \
     62         (
     63           pReq->config_2dot4g_sdf ? (SIZEOF_TLV_HDR + \
     64           sizeof(pReq->sdf_2dot4g_val)) : 0 \
     65         ) + \
     66         (
     67           pReq->config_5g_beacons ? (SIZEOF_TLV_HDR + \
     68           sizeof(pReq->beacon_5g_val)) : 0 \
     69         ) + \
     70         (
     71           pReq->config_5g_sdf ? (SIZEOF_TLV_HDR + \
     72           sizeof(pReq->sdf_5g_val)) : 0 \
     73         ) + \
     74         (
     75           pReq->config_5g_rssi_close ? (SIZEOF_TLV_HDR + \
     76           sizeof(pReq->rssi_close_5g_val)) : 0 \
     77         ) + \
     78         (
     79           pReq->config_5g_rssi_middle ? (SIZEOF_TLV_HDR + \
     80           sizeof(pReq->rssi_middle_5g_val)) : 0 \
     81         ) + \
     82         (
     83           pReq->config_2dot4g_rssi_proximity ? (SIZEOF_TLV_HDR + \
     84           sizeof(pReq->rssi_proximity_2dot4g_val)) : 0 \
     85         ) + \
     86         (
     87           pReq->config_5g_rssi_close_proximity ? (SIZEOF_TLV_HDR + \
     88           sizeof(pReq->rssi_close_proximity_5g_val)) : 0 \
     89         ) + \
     90         (
     91           pReq->config_rssi_window_size ? (SIZEOF_TLV_HDR + \
     92           sizeof(pReq->rssi_window_size_val)) : 0 \
     93         ) + \
     94         (
     95           pReq->config_oui ? (SIZEOF_TLV_HDR + \
     96           sizeof(pReq->oui_val)) : 0 \
     97         ) + \
     98         (
     99           pReq->config_intf_addr ? (SIZEOF_TLV_HDR + \
    100           sizeof(pReq->intf_addr_val)) : 0 \
    101         ) + \
    102         (
    103           pReq->config_cluster_attribute_val ? (SIZEOF_TLV_HDR + \
    104           sizeof(pReq->config_cluster_attribute_val)) : 0 \
    105         ) + \
    106         (
    107           pReq->config_scan_params ? (SIZEOF_TLV_HDR + \
    108           NAN_MAX_SOCIAL_CHANNELS * sizeof(u32)) : 0 \
    109         ) + \
    110         (
    111           pReq->config_random_factor_force ? (SIZEOF_TLV_HDR + \
    112           sizeof(pReq->random_factor_force_val)) : 0 \
    113         ) + \
    114         (
    115           pReq->config_hop_count_force ? (SIZEOF_TLV_HDR + \
    116           sizeof(pReq->hop_count_force_val)) : 0 \
    117         ) + \
    118         (
    119           pReq->config_24g_channel ? (SIZEOF_TLV_HDR + \
    120           sizeof(u32)) : 0 \
    121         ) + \
    122         (
    123           pReq->config_5g_channel ? (SIZEOF_TLV_HDR + \
    124           sizeof(u32)) : 0 \
    125         );
    126     pNanEnableReqMsg pFwReq = (pNanEnableReqMsg)malloc(message_len);
    127     if (pFwReq == NULL) {
    128         cleanup();
    129         return WIFI_ERROR_OUT_OF_MEMORY;
    130     }
    131 
    132     ALOGV("Message Len %zu", message_len);
    133     memset (pFwReq, 0, message_len);
    134     pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
    135     pFwReq->fwHeader.msgId = NAN_MSG_ID_ENABLE_REQ;
    136     pFwReq->fwHeader.msgLen = message_len;
    137     pFwReq->fwHeader.transactionId = id;
    138 
    139     u8* tlvs = pFwReq->ptlv;
    140 
    141     /* Write the TLVs to the message. */
    142 
    143     tlvs = addTlv(NAN_TLV_TYPE_CLUSTER_ID_LOW, sizeof(pReq->cluster_low),
    144                   (const u8*)&pReq->cluster_low, tlvs);
    145     tlvs = addTlv(NAN_TLV_TYPE_CLUSTER_ID_HIGH, sizeof(pReq->cluster_high),
    146                   (const u8*)&pReq->cluster_high, tlvs);
    147     tlvs = addTlv(NAN_TLV_TYPE_MASTER_PREFERENCE, sizeof(pReq->master_pref),
    148                   (const u8*)&pReq->master_pref, tlvs);
    149     if (pReq->config_support_5g) {
    150         tlvs = addTlv(NAN_TLV_TYPE_5G_SUPPORT, sizeof(pReq->support_5g_val),
    151                      (const u8*)&pReq->support_5g_val, tlvs);
    152     }
    153     if (pReq->config_sid_beacon) {
    154         tlvs = addTlv(NAN_TLV_TYPE_SID_BEACON, sizeof(pReq->sid_beacon_val),
    155                       (const u8*)&pReq->sid_beacon_val, tlvs);
    156     }
    157     if (pReq->config_2dot4g_rssi_close) {
    158         tlvs = addTlv(NAN_TLV_TYPE_24G_RSSI_CLOSE,
    159                       sizeof(pReq->rssi_close_2dot4g_val),
    160                       (const u8*)&pReq->rssi_close_2dot4g_val, tlvs);
    161     }
    162     if (pReq->config_2dot4g_rssi_middle) {
    163         tlvs = addTlv(NAN_TLV_TYPE_24G_RSSI_MIDDLE,
    164                       sizeof(pReq->rssi_middle_2dot4g_val),
    165                       (const u8*)&pReq->rssi_middle_2dot4g_val, tlvs);
    166     }
    167     if (pReq->config_hop_count_limit) {
    168         tlvs = addTlv(NAN_TLV_TYPE_HOP_COUNT_LIMIT,
    169                       sizeof(pReq->hop_count_limit_val),
    170                       (const u8*)&pReq->hop_count_limit_val, tlvs);
    171     }
    172     if (pReq->config_2dot4g_support) {
    173         tlvs = addTlv(NAN_TLV_TYPE_24G_SUPPORT, sizeof(pReq->support_2dot4g_val),
    174                       (const u8*)&pReq->support_2dot4g_val, tlvs);
    175     }
    176     if (pReq->config_2dot4g_beacons) {
    177         tlvs = addTlv(NAN_TLV_TYPE_24G_BEACON, sizeof(pReq->beacon_2dot4g_val),
    178                       (const u8*)&pReq->beacon_2dot4g_val, tlvs);
    179     }
    180     if (pReq->config_2dot4g_sdf) {
    181         tlvs = addTlv(NAN_TLV_TYPE_24G_SDF, sizeof(pReq->sdf_2dot4g_val),
    182                       (const u8*)&pReq->sdf_2dot4g_val, tlvs);
    183     }
    184     if (pReq->config_5g_beacons) {
    185         tlvs = addTlv(NAN_TLV_TYPE_5G_BEACON, sizeof(pReq->beacon_5g_val),
    186                       (const u8*)&pReq->beacon_5g_val, tlvs);
    187     }
    188     if (pReq->config_5g_sdf) {
    189         tlvs = addTlv(NAN_TLV_TYPE_5G_SDF, sizeof(pReq->sdf_5g_val),
    190                       (const u8*)&pReq->sdf_5g_val, tlvs);
    191     }
    192     if (pReq->config_2dot4g_rssi_proximity) {
    193         tlvs = addTlv(NAN_TLV_TYPE_24G_RSSI_CLOSE_PROXIMITY,
    194                       sizeof(pReq->rssi_proximity_2dot4g_val),
    195                       (const u8*)&pReq->rssi_proximity_2dot4g_val, tlvs);
    196     }
    197     /* Add the support of sending 5G RSSI values */
    198     if (pReq->config_5g_rssi_close) {
    199         tlvs = addTlv(NAN_TLV_TYPE_5G_RSSI_CLOSE, sizeof(pReq->rssi_close_5g_val),
    200                       (const u8*)&pReq->rssi_close_5g_val, tlvs);
    201     }
    202     if (pReq->config_5g_rssi_middle) {
    203         tlvs = addTlv(NAN_TLV_TYPE_5G_RSSI_MIDDLE, sizeof(pReq->rssi_middle_5g_val),
    204                       (const u8*)&pReq->rssi_middle_5g_val, tlvs);
    205     }
    206     if (pReq->config_5g_rssi_close_proximity) {
    207         tlvs = addTlv(NAN_TLV_TYPE_5G_RSSI_CLOSE_PROXIMITY,
    208                       sizeof(pReq->rssi_close_proximity_5g_val),
    209                       (const u8*)&pReq->rssi_close_proximity_5g_val, tlvs);
    210     }
    211     if (pReq->config_rssi_window_size) {
    212         tlvs = addTlv(NAN_TLV_TYPE_RSSI_AVERAGING_WINDOW_SIZE, sizeof(pReq->rssi_window_size_val),
    213                       (const u8*)&pReq->rssi_window_size_val, tlvs);
    214     }
    215     if (pReq->config_oui) {
    216         tlvs = addTlv(NAN_TLV_TYPE_CLUSTER_OUI_NETWORK_ID, sizeof(pReq->oui_val),
    217                       (const u8*)&pReq->oui_val, tlvs);
    218     }
    219     if (pReq->config_intf_addr) {
    220         tlvs = addTlv(NAN_TLV_TYPE_SOURCE_MAC_ADDRESS, sizeof(pReq->intf_addr_val),
    221                       (const u8*)&pReq->intf_addr_val[0], tlvs);
    222     }
    223     if (pReq->config_cluster_attribute_val) {
    224         tlvs = addTlv(NAN_TLV_TYPE_CLUSTER_ATTRIBUTE_IN_SDF, sizeof(pReq->config_cluster_attribute_val),
    225                       (const u8*)&pReq->config_cluster_attribute_val, tlvs);
    226     }
    227     if (pReq->config_scan_params) {
    228         u32 socialChannelParamVal[NAN_MAX_SOCIAL_CHANNELS];
    229         /* Fill the social channel param */
    230         fillNanSocialChannelParamVal(&pReq->scan_params_val,
    231                                      socialChannelParamVal);
    232         int i;
    233         for (i = 0; i < NAN_MAX_SOCIAL_CHANNELS; i++) {
    234             tlvs = addTlv(NAN_TLV_TYPE_SOCIAL_CHANNEL_SCAN_PARAMS,
    235                           sizeof(socialChannelParamVal[i]),
    236                           (const u8*)&socialChannelParamVal[i], tlvs);
    237         }
    238     }
    239     if (pReq->config_random_factor_force) {
    240         tlvs = addTlv(NAN_TLV_TYPE_RANDOM_FACTOR_FORCE,
    241                       sizeof(pReq->random_factor_force_val),
    242                       (const u8*)&pReq->random_factor_force_val, tlvs);
    243     }
    244     if (pReq->config_hop_count_force) {
    245         tlvs = addTlv(NAN_TLV_TYPE_HOP_COUNT_FORCE,
    246                       sizeof(pReq->hop_count_force_val),
    247                       (const u8*)&pReq->hop_count_force_val, tlvs);
    248     }
    249     if (pReq->config_24g_channel) {
    250         tlvs = addTlv(NAN_TLV_TYPE_24G_CHANNEL,
    251                       sizeof(u32),
    252                       (const u8*)&pReq->channel_24g_val, tlvs);
    253     }
    254     if (pReq->config_5g_channel) {
    255         tlvs = addTlv(NAN_TLV_TYPE_5G_CHANNEL,
    256                       sizeof(u32),
    257                       (const u8*)&pReq->channel_5g_val, tlvs);
    258     }
    259     mVendorData = (char*)pFwReq;
    260     mDataLen = message_len;
    261 
    262     //Insert the vendor specific data
    263     int ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
    264     if (ret < 0) {
    265         ALOGE("%s: put_bytes Error:%d",__func__, ret);
    266         cleanup();
    267         return ret;
    268     }
    269     hexdump(mVendorData, mDataLen);
    270     return ret;
    271 }
    272 
    273 int NanCommand::putNanDisable(transaction_id id)
    274 {
    275     ALOGV("NAN_DISABLE");
    276     size_t message_len = sizeof(NanDisableReqMsg);
    277 
    278     pNanDisableReqMsg pFwReq = (pNanDisableReqMsg)malloc(message_len);
    279     if (pFwReq == NULL) {
    280         cleanup();
    281         return WIFI_ERROR_OUT_OF_MEMORY;
    282     }
    283 
    284     ALOGV("Message Len %zu", message_len);
    285     memset (pFwReq, 0, message_len);
    286     pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
    287     pFwReq->fwHeader.msgId = NAN_MSG_ID_DISABLE_REQ;
    288     pFwReq->fwHeader.msgLen = message_len;
    289     pFwReq->fwHeader.transactionId = id;
    290 
    291     mVendorData = (char*)pFwReq;
    292     mDataLen = message_len;
    293 
    294     int ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
    295     if (ret < 0) {
    296         ALOGE("%s: put_bytes Error:%d",__func__, ret);
    297         cleanup();
    298         return ret;
    299     }
    300     hexdump(mVendorData, mDataLen);
    301     return ret;
    302 }
    303 
    304 int NanCommand::putNanConfig(transaction_id id, const NanConfigRequest *pReq)
    305 {
    306     ALOGV("NAN_CONFIG");
    307     size_t message_len = NAN_MAX_CONFIGURATION_REQ_SIZE;
    308     int idx = 0;
    309 
    310     if (pReq == NULL ||
    311         pReq->num_config_discovery_attr > NAN_MAX_POSTDISCOVERY_LEN) {
    312         cleanup();
    313         return WIFI_ERROR_INVALID_ARGS;
    314     }
    315 
    316     message_len = sizeof(NanMsgHeader);
    317 
    318     message_len += \
    319          (
    320            pReq->config_sid_beacon ? (SIZEOF_TLV_HDR + \
    321            sizeof(pReq->sid_beacon)) : 0 \
    322          ) + \
    323          (
    324            pReq->config_master_pref ? (SIZEOF_TLV_HDR + \
    325            sizeof(pReq->master_pref)) : 0 \
    326          ) + \
    327          (
    328            pReq->config_rssi_proximity ? (SIZEOF_TLV_HDR + \
    329            sizeof(pReq->rssi_proximity)) : 0 \
    330          ) + \
    331          (
    332            pReq->config_5g_rssi_close_proximity ? (SIZEOF_TLV_HDR + \
    333            sizeof(pReq->rssi_close_proximity_5g_val)) : 0 \
    334          ) + \
    335          (
    336            pReq->config_rssi_window_size ? (SIZEOF_TLV_HDR + \
    337            sizeof(pReq->rssi_window_size_val)) : 0 \
    338          ) + \
    339          (
    340            pReq->config_cluster_attribute_val ? (SIZEOF_TLV_HDR + \
    341            sizeof(pReq->config_cluster_attribute_val)) : 0 \
    342          ) + \
    343          (
    344            pReq->config_scan_params ? (SIZEOF_TLV_HDR + \
    345            NAN_MAX_SOCIAL_CHANNELS * sizeof(u32)) : 0 \
    346          ) + \
    347          (
    348            pReq->config_random_factor_force ? (SIZEOF_TLV_HDR + \
    349            sizeof(pReq->random_factor_force_val)) : 0 \
    350           ) + \
    351          (
    352            pReq->config_hop_count_force ? (SIZEOF_TLV_HDR + \
    353            sizeof(pReq->hop_count_force_val)) : 0 \
    354          ) + \
    355          (
    356            pReq->config_conn_capability ? (SIZEOF_TLV_HDR + \
    357            sizeof(u32)) : 0 \
    358          );
    359 
    360     if (pReq->num_config_discovery_attr) {
    361         for (idx = 0; idx < pReq->num_config_discovery_attr; idx ++) {
    362             message_len += SIZEOF_TLV_HDR +\
    363                 calcNanTransmitPostDiscoverySize(&pReq->discovery_attr_val[idx]);
    364         }
    365     }
    366 
    367     if (pReq->config_fam && \
    368         calcNanFurtherAvailabilityMapSize(&pReq->fam_val)) {
    369         message_len += (SIZEOF_TLV_HDR + \
    370            calcNanFurtherAvailabilityMapSize(&pReq->fam_val));
    371     }
    372 
    373     pNanConfigurationReqMsg pFwReq = (pNanConfigurationReqMsg)malloc(message_len);
    374     if (pFwReq == NULL) {
    375         cleanup();
    376         return WIFI_ERROR_OUT_OF_MEMORY;
    377     }
    378 
    379     ALOGV("Message Len %zu", message_len);
    380     memset (pFwReq, 0, message_len);
    381     pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
    382     pFwReq->fwHeader.msgId = NAN_MSG_ID_CONFIGURATION_REQ;
    383     pFwReq->fwHeader.msgLen = message_len;
    384     pFwReq->fwHeader.transactionId = id;
    385 
    386     u8* tlvs = pFwReq->ptlv;
    387     if (pReq->config_sid_beacon) {
    388         tlvs = addTlv(NAN_TLV_TYPE_SID_BEACON, sizeof(pReq->sid_beacon),
    389                       (const u8*)&pReq->sid_beacon, tlvs);
    390     }
    391     if (pReq->config_master_pref) {
    392         tlvs = addTlv(NAN_TLV_TYPE_MASTER_PREFERENCE, sizeof(pReq->master_pref),
    393                       (const u8*)&pReq->master_pref, tlvs);
    394     }
    395 
    396     if (pReq->config_rssi_window_size) {
    397         tlvs = addTlv(NAN_TLV_TYPE_RSSI_AVERAGING_WINDOW_SIZE, sizeof(pReq->rssi_window_size_val),
    398                       (const u8*)&pReq->rssi_window_size_val, tlvs);
    399     }
    400     if (pReq->config_rssi_proximity) {
    401         tlvs = addTlv(NAN_TLV_TYPE_24G_RSSI_CLOSE_PROXIMITY, sizeof(pReq->rssi_proximity),
    402                       (const u8*)&pReq->rssi_proximity, tlvs);
    403     }
    404     if (pReq->config_scan_params) {
    405         u32 socialChannelParamVal[NAN_MAX_SOCIAL_CHANNELS];
    406         /* Fill the social channel param */
    407         fillNanSocialChannelParamVal(&pReq->scan_params_val,
    408                                  socialChannelParamVal);
    409         int i;
    410         for (i = 0; i < NAN_MAX_SOCIAL_CHANNELS; i++) {
    411             tlvs = addTlv(NAN_TLV_TYPE_SOCIAL_CHANNEL_SCAN_PARAMS,
    412                           sizeof(socialChannelParamVal[i]),
    413                           (const u8*)&socialChannelParamVal[i], tlvs);
    414         }
    415     }
    416     if (pReq->config_random_factor_force) {
    417         tlvs = addTlv(NAN_TLV_TYPE_RANDOM_FACTOR_FORCE,
    418                       sizeof(pReq->random_factor_force_val),
    419                       (const u8*)&pReq->random_factor_force_val, tlvs);
    420     }
    421     if (pReq->config_hop_count_force) {
    422         tlvs = addTlv(NAN_TLV_TYPE_HOP_COUNT_FORCE,
    423                       sizeof(pReq->hop_count_force_val),
    424                       (const u8*)&pReq->hop_count_force_val, tlvs);
    425     }
    426     if (pReq->config_conn_capability) {
    427         u32 val = \
    428         getNanTransmitPostConnectivityCapabilityVal(&pReq->conn_capability_val);
    429         tlvs = addTlv(NAN_TLV_TYPE_POST_NAN_CONNECTIVITY_CAPABILITIES_TRANSMIT,
    430                       sizeof(val), (const u8*)&val, tlvs);
    431     }
    432     if (pReq->num_config_discovery_attr) {
    433         for (idx = 0; idx < pReq->num_config_discovery_attr; idx ++) {
    434             fillNanTransmitPostDiscoveryVal(&pReq->discovery_attr_val[idx],
    435                                             (u8*)(tlvs + SIZEOF_TLV_HDR));
    436             tlvs = addTlv(NAN_TLV_TYPE_POST_NAN_DISCOVERY_ATTRIBUTE_TRANSMIT,
    437                           calcNanTransmitPostDiscoverySize(
    438                               &pReq->discovery_attr_val[idx]),
    439                           (const u8*)(tlvs + SIZEOF_TLV_HDR), tlvs);
    440         }
    441     }
    442     if (pReq->config_fam && \
    443         calcNanFurtherAvailabilityMapSize(&pReq->fam_val)) {
    444         fillNanFurtherAvailabilityMapVal(&pReq->fam_val,
    445                                         (u8*)(tlvs + SIZEOF_TLV_HDR));
    446         tlvs = addTlv(NAN_TLV_TYPE_FURTHER_AVAILABILITY_MAP,
    447                       calcNanFurtherAvailabilityMapSize(&pReq->fam_val),
    448                       (const u8*)(tlvs + SIZEOF_TLV_HDR), tlvs);
    449     }
    450 
    451     mVendorData = (char*)pFwReq;
    452     mDataLen = message_len;
    453 
    454     int ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
    455     if (ret < 0) {
    456         ALOGE("%s: put_bytes Error:%d",__func__, ret);
    457         cleanup();
    458         return ret;
    459     }
    460     hexdump(mVendorData, mDataLen);
    461     return ret;
    462 }
    463 
    464 
    465 int NanCommand::putNanPublish(transaction_id id, const NanPublishRequest *pReq)
    466 {
    467     ALOGV("NAN_PUBLISH");
    468     if (pReq == NULL) {
    469         cleanup();
    470         return WIFI_ERROR_INVALID_ARGS;
    471     }
    472 
    473     size_t message_len =
    474         sizeof(NanMsgHeader) + sizeof(NanPublishServiceReqParams) +
    475         (pReq->service_name_len ? SIZEOF_TLV_HDR + pReq->service_name_len : 0) +
    476         (pReq->service_specific_info_len ? SIZEOF_TLV_HDR + pReq->service_specific_info_len : 0) +
    477         (pReq->rx_match_filter_len ? SIZEOF_TLV_HDR + pReq->rx_match_filter_len : 0) +
    478         (pReq->tx_match_filter_len ? SIZEOF_TLV_HDR + pReq->tx_match_filter_len : 0);
    479 
    480     pNanPublishServiceReqMsg pFwReq = (pNanPublishServiceReqMsg)malloc(message_len);
    481     if (pFwReq == NULL) {
    482         cleanup();
    483         return WIFI_ERROR_OUT_OF_MEMORY;
    484     }
    485 
    486     ALOGV("Message Len %zu", message_len);
    487     memset(pFwReq, 0, message_len);
    488     pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
    489     pFwReq->fwHeader.msgId = NAN_MSG_ID_PUBLISH_SERVICE_REQ;
    490     pFwReq->fwHeader.msgLen = message_len;
    491     if (pReq->publish_id == 0) {
    492         pFwReq->fwHeader.handle = 0xFFFF;
    493     } else {
    494         pFwReq->fwHeader.handle = pReq->publish_id;
    495     }
    496     pFwReq->fwHeader.transactionId = id;
    497 
    498     pFwReq->publishServiceReqParams.ttl = pReq->ttl;
    499     pFwReq->publishServiceReqParams.period = pReq->period;
    500     pFwReq->publishServiceReqParams.reserved = 0;
    501     pFwReq->publishServiceReqParams.publishType = pReq->publish_type;
    502     pFwReq->publishServiceReqParams.txType = pReq->tx_type;
    503 
    504     pFwReq->publishServiceReqParams.rssiThresholdFlag = pReq->rssi_threshold_flag;
    505     pFwReq->publishServiceReqParams.matchAlg = pReq->publish_match_indicator;
    506     pFwReq->publishServiceReqParams.count = pReq->publish_count;
    507     pFwReq->publishServiceReqParams.connmap = pReq->connmap;
    508     pFwReq->publishServiceReqParams.pubTerminatedIndDisableFlag =
    509                                    (pReq->recv_indication_cfg & BIT_0) ? 1 : 0;
    510     pFwReq->publishServiceReqParams.pubMatchExpiredIndDisableFlag =
    511                                    (pReq->recv_indication_cfg & BIT_1) ? 1 : 0;
    512     pFwReq->publishServiceReqParams.followupRxIndDisableFlag =
    513                                    (pReq->recv_indication_cfg & BIT_2) ? 1 : 0;
    514 
    515     pFwReq->publishServiceReqParams.reserved2 = 0;
    516 
    517     u8* tlvs = pFwReq->ptlv;
    518     if (pReq->service_name_len) {
    519         tlvs = addTlv(NAN_TLV_TYPE_SERVICE_NAME, pReq->service_name_len,
    520                       (const u8*)&pReq->service_name[0], tlvs);
    521     }
    522     if (pReq->service_specific_info_len) {
    523         tlvs = addTlv(NAN_TLV_TYPE_SERVICE_SPECIFIC_INFO, pReq->service_specific_info_len,
    524                       (const u8*)&pReq->service_specific_info[0], tlvs);
    525     }
    526     if (pReq->rx_match_filter_len) {
    527         tlvs = addTlv(NAN_TLV_TYPE_RX_MATCH_FILTER, pReq->rx_match_filter_len,
    528                       (const u8*)&pReq->rx_match_filter[0], tlvs);
    529     }
    530     if (pReq->tx_match_filter_len) {
    531         tlvs = addTlv(NAN_TLV_TYPE_TX_MATCH_FILTER, pReq->tx_match_filter_len,
    532                       (const u8*)&pReq->tx_match_filter[0], tlvs);
    533     }
    534 
    535     mVendorData = (char *)pFwReq;
    536     mDataLen = message_len;
    537 
    538     int ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
    539     if (ret < 0) {
    540         ALOGE("%s: put_bytes Error:%d",__func__, ret);
    541         cleanup();
    542         return ret;
    543     }
    544     hexdump(mVendorData, mDataLen);
    545     return ret;
    546 }
    547 
    548 int NanCommand::putNanPublishCancel(transaction_id id, const NanPublishCancelRequest *pReq)
    549 {
    550     ALOGV("NAN_PUBLISH_CANCEL");
    551     if (pReq == NULL) {
    552         cleanup();
    553         return WIFI_ERROR_INVALID_ARGS;
    554     }
    555     size_t message_len = sizeof(NanPublishServiceCancelReqMsg);
    556 
    557     pNanPublishServiceCancelReqMsg pFwReq =
    558         (pNanPublishServiceCancelReqMsg)malloc(message_len);
    559     if (pFwReq == NULL) {
    560         cleanup();
    561         return WIFI_ERROR_OUT_OF_MEMORY;
    562     }
    563 
    564     ALOGV("Message Len %zu", message_len);
    565     memset(pFwReq, 0, message_len);
    566     pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
    567     pFwReq->fwHeader.msgId = NAN_MSG_ID_PUBLISH_SERVICE_CANCEL_REQ;
    568     pFwReq->fwHeader.msgLen = message_len;
    569     pFwReq->fwHeader.handle = pReq->publish_id;
    570     pFwReq->fwHeader.transactionId = id;
    571 
    572     mVendorData = (char *)pFwReq;
    573     mDataLen = message_len;
    574 
    575     int ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
    576     if (ret < 0) {
    577         ALOGE("%s: put_bytes Error:%d",__func__, ret);
    578         cleanup();
    579         return ret;
    580     }
    581     hexdump(mVendorData, mDataLen);
    582     return ret;
    583 }
    584 
    585 int NanCommand::putNanSubscribe(transaction_id id,
    586                                 const NanSubscribeRequest *pReq)
    587 {
    588 
    589     ALOGV("NAN_SUBSCRIBE");
    590     if (pReq == NULL) {
    591         cleanup();
    592         return WIFI_ERROR_INVALID_ARGS;
    593     }
    594 
    595     size_t message_len =
    596         sizeof(NanMsgHeader) + sizeof(NanSubscribeServiceReqParams) +
    597         (pReq->service_name_len ? SIZEOF_TLV_HDR + pReq->service_name_len : 0) +
    598         (pReq->service_specific_info_len ? SIZEOF_TLV_HDR + pReq->service_specific_info_len : 0) +
    599         (pReq->rx_match_filter_len ? SIZEOF_TLV_HDR + pReq->rx_match_filter_len : 0) +
    600         (pReq->tx_match_filter_len ? SIZEOF_TLV_HDR + pReq->tx_match_filter_len : 0);
    601 
    602     message_len += \
    603         (pReq->num_intf_addr_present * (SIZEOF_TLV_HDR + NAN_MAC_ADDR_LEN));
    604 
    605     pNanSubscribeServiceReqMsg pFwReq = (pNanSubscribeServiceReqMsg)malloc(message_len);
    606     if (pFwReq == NULL) {
    607         cleanup();
    608         return WIFI_ERROR_OUT_OF_MEMORY;
    609     }
    610 
    611     ALOGV("Message Len %zu", message_len);
    612     memset(pFwReq, 0, message_len);
    613     pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
    614     pFwReq->fwHeader.msgId = NAN_MSG_ID_SUBSCRIBE_SERVICE_REQ;
    615     pFwReq->fwHeader.msgLen = message_len;
    616     if (pReq->subscribe_id == 0) {
    617         pFwReq->fwHeader.handle = 0xFFFF;
    618     } else {
    619         pFwReq->fwHeader.handle = pReq->subscribe_id;
    620     }
    621     pFwReq->fwHeader.transactionId = id;
    622 
    623     pFwReq->subscribeServiceReqParams.ttl = pReq->ttl;
    624     pFwReq->subscribeServiceReqParams.period = pReq->period;
    625     pFwReq->subscribeServiceReqParams.subscribeType = pReq->subscribe_type;
    626     pFwReq->subscribeServiceReqParams.srfAttr = pReq->serviceResponseFilter;
    627     pFwReq->subscribeServiceReqParams.srfInclude = pReq->serviceResponseInclude;
    628     pFwReq->subscribeServiceReqParams.srfSend = pReq->useServiceResponseFilter;
    629     pFwReq->subscribeServiceReqParams.ssiRequired = pReq->ssiRequiredForMatchIndication;
    630     pFwReq->subscribeServiceReqParams.matchAlg = pReq->subscribe_match_indicator;
    631     pFwReq->subscribeServiceReqParams.count = pReq->subscribe_count;
    632     pFwReq->subscribeServiceReqParams.rssiThresholdFlag = pReq->rssi_threshold_flag;
    633     pFwReq->subscribeServiceReqParams.subTerminatedIndDisableFlag =
    634                                    (pReq->recv_indication_cfg & BIT_0) ? 1 : 0;
    635     pFwReq->subscribeServiceReqParams.subMatchExpiredIndDisableFlag =
    636                                    (pReq->recv_indication_cfg & BIT_1) ? 1 : 0;
    637     pFwReq->subscribeServiceReqParams.followupRxIndDisableFlag =
    638                                    (pReq->recv_indication_cfg & BIT_2) ? 1 : 0;
    639     pFwReq->subscribeServiceReqParams.connmap = pReq->connmap;
    640     pFwReq->subscribeServiceReqParams.reserved = 0;
    641 
    642     u8* tlvs = pFwReq->ptlv;
    643     if (pReq->service_name_len) {
    644         tlvs = addTlv(NAN_TLV_TYPE_SERVICE_NAME, pReq->service_name_len,
    645                       (const u8*)&pReq->service_name[0], tlvs);
    646     }
    647     if (pReq->service_specific_info_len) {
    648         tlvs = addTlv(NAN_TLV_TYPE_SERVICE_SPECIFIC_INFO, pReq->service_specific_info_len,
    649                       (const u8*)&pReq->service_specific_info[0], tlvs);
    650     }
    651     if (pReq->rx_match_filter_len) {
    652         tlvs = addTlv(NAN_TLV_TYPE_RX_MATCH_FILTER, pReq->rx_match_filter_len,
    653                       (const u8*)&pReq->rx_match_filter[0], tlvs);
    654     }
    655     if (pReq->tx_match_filter_len) {
    656         tlvs = addTlv(NAN_TLV_TYPE_TX_MATCH_FILTER, pReq->tx_match_filter_len,
    657                       (const u8*)&pReq->tx_match_filter[0], tlvs);
    658     }
    659 
    660     int i = 0;
    661     for (i = 0; i < pReq->num_intf_addr_present; i++)
    662     {
    663         tlvs = addTlv(NAN_TLV_TYPE_MAC_ADDRESS,
    664                       NAN_MAC_ADDR_LEN,
    665                       (const u8*)&pReq->intf_addr[i][0], tlvs);
    666     }
    667 
    668     mVendorData = (char *)pFwReq;
    669     mDataLen = message_len;
    670     int ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
    671     if (ret < 0) {
    672         ALOGE("%s: put_bytes Error:%d",__func__, ret);
    673         cleanup();
    674         return ret;
    675     }
    676     hexdump(mVendorData, mDataLen);
    677     return ret;
    678 }
    679 
    680 int NanCommand::putNanSubscribeCancel(transaction_id id,
    681                                       const NanSubscribeCancelRequest *pReq)
    682 {
    683     ALOGV("NAN_SUBSCRIBE_CANCEL");
    684     if (pReq == NULL) {
    685         cleanup();
    686         return WIFI_ERROR_INVALID_ARGS;
    687     }
    688     size_t message_len = sizeof(NanSubscribeServiceCancelReqMsg);
    689 
    690     pNanSubscribeServiceCancelReqMsg pFwReq =
    691         (pNanSubscribeServiceCancelReqMsg)malloc(message_len);
    692     if (pFwReq == NULL) {
    693         cleanup();
    694         return WIFI_ERROR_OUT_OF_MEMORY;
    695     }
    696 
    697     ALOGV("Message Len %zu", message_len);
    698     memset(pFwReq, 0, message_len);
    699     pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
    700     pFwReq->fwHeader.msgId = NAN_MSG_ID_SUBSCRIBE_SERVICE_CANCEL_REQ;
    701     pFwReq->fwHeader.msgLen = message_len;
    702     pFwReq->fwHeader.handle = pReq->subscribe_id;
    703     pFwReq->fwHeader.transactionId = id;
    704 
    705     mVendorData = (char *)pFwReq;
    706     mDataLen = message_len;
    707     int ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
    708     if (ret < 0) {
    709         ALOGE("%s: put_bytes Error:%d",__func__, ret);
    710         cleanup();
    711         return ret;
    712     }
    713     hexdump(mVendorData, mDataLen);
    714     return ret;
    715 }
    716 
    717 
    718 int NanCommand::putNanTransmitFollowup(transaction_id id,
    719                                        const NanTransmitFollowupRequest *pReq)
    720 {
    721     ALOGV("TRANSMIT_FOLLOWUP");
    722     if (pReq == NULL) {
    723         cleanup();
    724         return WIFI_ERROR_INVALID_ARGS;
    725     }
    726 
    727     size_t message_len =
    728         sizeof(NanMsgHeader) + sizeof(NanTransmitFollowupReqParams) +
    729         (pReq->service_specific_info_len ? SIZEOF_TLV_HDR +
    730          pReq->service_specific_info_len : 0);
    731 
    732     /* Mac address needs to be added in TLV */
    733     message_len += (SIZEOF_TLV_HDR + sizeof(pReq->addr));
    734 
    735     pNanTransmitFollowupReqMsg pFwReq = (pNanTransmitFollowupReqMsg)malloc(message_len);
    736     if (pFwReq == NULL) {
    737         cleanup();
    738         return WIFI_ERROR_OUT_OF_MEMORY;
    739     }
    740 
    741     ALOGV("Message Len %zu", message_len);
    742     memset (pFwReq, 0, message_len);
    743     pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
    744     pFwReq->fwHeader.msgId = NAN_MSG_ID_TRANSMIT_FOLLOWUP_REQ;
    745     pFwReq->fwHeader.msgLen = message_len;
    746     pFwReq->fwHeader.handle = pReq->publish_subscribe_id;
    747     pFwReq->fwHeader.transactionId = id;
    748 
    749     pFwReq->transmitFollowupReqParams.matchHandle = pReq->requestor_instance_id;
    750     if (pReq->priority != NAN_TX_PRIORITY_HIGH) {
    751         pFwReq->transmitFollowupReqParams.priority = 1;
    752     } else {
    753         pFwReq->transmitFollowupReqParams.priority = 2;
    754     }
    755     pFwReq->transmitFollowupReqParams.window = pReq->dw_or_faw;
    756     pFwReq->transmitFollowupReqParams.followupTxRspDisableFlag =
    757                                    (pReq->recv_indication_cfg & BIT_0) ? 1 : 0;
    758     pFwReq->transmitFollowupReqParams.reserved = 0;
    759 
    760     u8* tlvs = pFwReq->ptlv;
    761 
    762     /* Mac address needs to be added in TLV */
    763     tlvs = addTlv(NAN_TLV_TYPE_MAC_ADDRESS, sizeof(pReq->addr),
    764                   (const u8*)&pReq->addr[0], tlvs);
    765     u16 tlv_type = NAN_TLV_TYPE_SERVICE_SPECIFIC_INFO;
    766 
    767     if (pReq->service_specific_info_len) {
    768         tlvs = addTlv(tlv_type, pReq->service_specific_info_len,
    769                       (const u8*)&pReq->service_specific_info[0], tlvs);
    770     }
    771 
    772     mVendorData = (char *)pFwReq;
    773     mDataLen = message_len;
    774 
    775     int ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
    776     if (ret < 0) {
    777         ALOGE("%s: put_bytes Error:%d",__func__, ret);
    778         cleanup();
    779         return ret;
    780     }
    781     hexdump(mVendorData, mDataLen);
    782     return ret;
    783 }
    784 
    785 int NanCommand::putNanStats(transaction_id id, const NanStatsRequest *pReq)
    786 {
    787     ALOGV("NAN_STATS");
    788     if (pReq == NULL) {
    789         cleanup();
    790         return WIFI_ERROR_INVALID_ARGS;
    791     }
    792     size_t message_len = sizeof(NanStatsReqMsg);
    793 
    794     pNanStatsReqMsg pFwReq =
    795         (pNanStatsReqMsg)malloc(message_len);
    796     if (pFwReq == NULL) {
    797         cleanup();
    798         return WIFI_ERROR_OUT_OF_MEMORY;
    799     }
    800 
    801     ALOGV("Message Len %zu", message_len);
    802     memset(pFwReq, 0, message_len);
    803     pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
    804     pFwReq->fwHeader.msgId = NAN_MSG_ID_STATS_REQ;
    805     pFwReq->fwHeader.msgLen = message_len;
    806     pFwReq->fwHeader.transactionId = id;
    807 
    808     pFwReq->statsReqParams.statsType = pReq->stats_type;
    809     pFwReq->statsReqParams.clear = pReq->clear;
    810     pFwReq->statsReqParams.reserved = 0;
    811 
    812     mVendorData = (char *)pFwReq;
    813     mDataLen = message_len;
    814 
    815     int ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
    816     if (ret < 0) {
    817         ALOGE("%s: put_bytes Error:%d",__func__, ret);
    818         cleanup();
    819         return ret;
    820     }
    821     hexdump(mVendorData, mDataLen);
    822     return ret;
    823 }
    824 
    825 int NanCommand::putNanTCA(transaction_id id, const NanTCARequest *pReq)
    826 {
    827     ALOGV("NAN_TCA");
    828     if (pReq == NULL) {
    829         cleanup();
    830         return WIFI_ERROR_INVALID_ARGS;
    831     }
    832     size_t message_len = sizeof(NanTcaReqMsg);
    833 
    834     message_len += (SIZEOF_TLV_HDR + 2 * sizeof(u32));
    835     pNanTcaReqMsg pFwReq =
    836         (pNanTcaReqMsg)malloc(message_len);
    837     if (pFwReq == NULL) {
    838         cleanup();
    839         return WIFI_ERROR_OUT_OF_MEMORY;
    840     }
    841 
    842     ALOGV("Message Len %zu", message_len);
    843     memset(pFwReq, 0, message_len);
    844     pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
    845     pFwReq->fwHeader.msgId = NAN_MSG_ID_TCA_REQ;
    846     pFwReq->fwHeader.msgLen = message_len;
    847     pFwReq->fwHeader.transactionId = id;
    848 
    849     u32 tcaReqParams[2];
    850     memset (tcaReqParams, 0, sizeof(tcaReqParams));
    851     tcaReqParams[0] = (pReq->rising_direction_evt_flag & 0x01);
    852     tcaReqParams[0] |= (pReq->falling_direction_evt_flag & 0x01) << 1;
    853     tcaReqParams[0] |= (pReq->clear & 0x01) << 2;
    854     tcaReqParams[1] = pReq->threshold;
    855 
    856     u8* tlvs = pFwReq->ptlv;
    857 
    858     if (pReq->tca_type == NAN_TCA_ID_CLUSTER_SIZE) {
    859         tlvs = addTlv(NAN_TLV_TYPE_CLUSTER_SIZE_REQ, sizeof(tcaReqParams),
    860                       (const u8*)&tcaReqParams[0], tlvs);
    861     }
    862     else {
    863         ALOGE("%s: Unrecognized tca_type:%u", __FUNCTION__, pReq->tca_type);
    864         cleanup();
    865         return WIFI_ERROR_INVALID_ARGS;
    866     }
    867 
    868     mVendorData = (char *)pFwReq;
    869     mDataLen = message_len;
    870 
    871     int ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
    872     if (ret < 0) {
    873         ALOGE("%s: put_bytes Error:%d",__func__, ret);
    874         cleanup();
    875         return ret;
    876     }
    877     hexdump(mVendorData, mDataLen);
    878     return ret;
    879 }
    880 
    881 int NanCommand::putNanBeaconSdfPayload(transaction_id id,
    882                                        const NanBeaconSdfPayloadRequest *pReq)
    883 {
    884     ALOGV("NAN_BEACON_SDF_PAYLAOD");
    885     if (pReq == NULL) {
    886         cleanup();
    887         return WIFI_ERROR_INVALID_ARGS;
    888     }
    889     size_t message_len = sizeof(NanMsgHeader) + \
    890         SIZEOF_TLV_HDR + sizeof(u32) + \
    891         pReq->vsa.vsa_len;
    892 
    893     pNanBeaconSdfPayloadReqMsg pFwReq =
    894         (pNanBeaconSdfPayloadReqMsg)malloc(message_len);
    895     if (pFwReq == NULL) {
    896         cleanup();
    897         return WIFI_ERROR_OUT_OF_MEMORY;
    898     }
    899 
    900     ALOGV("Message Len %zu", message_len);
    901     memset(pFwReq, 0, message_len);
    902     pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
    903     pFwReq->fwHeader.msgId = NAN_MSG_ID_BEACON_SDF_REQ;
    904     pFwReq->fwHeader.msgLen = message_len;
    905     pFwReq->fwHeader.transactionId = id;
    906 
    907     /* Construct First 4 bytes of NanBeaconSdfPayloadReqMsg */
    908     u32 temp = 0;
    909     temp = pReq->vsa.payload_transmit_flag & 0x01;
    910     temp |= (pReq->vsa.tx_in_discovery_beacon & 0x01) << 1;
    911     temp |= (pReq->vsa.tx_in_sync_beacon & 0x01) << 2;
    912     temp |= (pReq->vsa.tx_in_service_discovery & 0x01) << 3;
    913     temp |= (pReq->vsa.vendor_oui & 0x00FFFFFF) << 8;
    914 
    915     int tlv_len = sizeof(u32) + pReq->vsa.vsa_len;
    916     u8* tempBuf = (u8*)malloc(tlv_len);
    917     if (tempBuf == NULL) {
    918         ALOGE("%s: Malloc failed", __func__);
    919         free(pFwReq);
    920         cleanup();
    921         return WIFI_ERROR_OUT_OF_MEMORY;
    922     }
    923     memset(tempBuf, 0, tlv_len);
    924     memcpy(tempBuf, &temp, sizeof(u32));
    925     memcpy((tempBuf + sizeof(u32)), pReq->vsa.vsa, pReq->vsa.vsa_len);
    926 
    927     u8* tlvs = pFwReq->ptlv;
    928 
    929     /* Write the TLVs to the message. */
    930     tlvs = addTlv(NAN_TLV_TYPE_VENDOR_SPECIFIC_ATTRIBUTE_TRANSMIT, tlv_len,
    931                   (const u8*)tempBuf, tlvs);
    932     free(tempBuf);
    933 
    934     mVendorData = (char *)pFwReq;
    935     mDataLen = message_len;
    936 
    937     int ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
    938     if (ret < 0) {
    939         ALOGE("%s: put_bytes Error:%d",__func__, ret);
    940         cleanup();
    941         return ret;
    942     }
    943     hexdump(mVendorData, mDataLen);
    944     return ret;
    945 }
    946 
    947 //callback handlers registered for nl message send
    948 static int error_handler_nan(struct sockaddr_nl *nla, struct nlmsgerr *err,
    949                          void *arg)
    950 {
    951     struct sockaddr_nl * tmp;
    952     int *ret = (int *)arg;
    953     tmp = nla;
    954     *ret = err->error;
    955     ALOGE("%s: Error code:%d (%s)", __func__, *ret, strerror(-(*ret)));
    956     return NL_STOP;
    957 }
    958 
    959 //callback handlers registered for nl message send
    960 static int ack_handler_nan(struct nl_msg *msg, void *arg)
    961 {
    962     int *ret = (int *)arg;
    963     struct nl_msg * a;
    964 
    965     ALOGE("%s: called", __func__);
    966     a = msg;
    967     *ret = 0;
    968     return NL_STOP;
    969 }
    970 
    971 //callback handlers registered for nl message send
    972 static int finish_handler_nan(struct nl_msg *msg, void *arg)
    973 {
    974   int *ret = (int *)arg;
    975   struct nl_msg * a;
    976 
    977   ALOGE("%s: called", __func__);
    978   a = msg;
    979   *ret = 0;
    980   return NL_SKIP;
    981 }
    982 
    983 
    984 //Override base class requestEvent and implement little differently here
    985 //This will send the request message
    986 //We dont wait for any response back in case of Nan as it is asynchronous
    987 //thus no wait for condition.
    988 int NanCommand::requestEvent()
    989 {
    990     int res;
    991     struct nl_cb * cb;
    992 
    993     cb = nl_cb_alloc(NL_CB_DEFAULT);
    994     if (!cb) {
    995         ALOGE("%s: Callback allocation failed",__func__);
    996         res = -1;
    997         goto out;
    998     }
    999 
   1000     /* send message */
   1001     ALOGV("%s:Handle:%p Socket Value:%p", __func__, mInfo, mInfo->cmd_sock);
   1002     res = nl_send_auto_complete(mInfo->cmd_sock, mMsg.getMessage());
   1003     if (res < 0)
   1004         goto out;
   1005     res = 1;
   1006 
   1007     nl_cb_err(cb, NL_CB_CUSTOM, error_handler_nan, &res);
   1008     nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler_nan, &res);
   1009     nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler_nan, &res);
   1010 
   1011     // err is populated as part of finish_handler
   1012     while (res > 0)
   1013         nl_recvmsgs(mInfo->cmd_sock, cb);
   1014 
   1015 out:
   1016     //free the VendorData
   1017     if (mVendorData) {
   1018         free(mVendorData);
   1019     }
   1020     mVendorData = NULL;
   1021     //cleanup the mMsg
   1022     mMsg.destroy();
   1023     return res;
   1024 }
   1025 
   1026 int NanCommand::calcNanTransmitPostDiscoverySize(
   1027     const NanTransmitPostDiscovery *pPostDiscovery)
   1028 {
   1029     /* Fixed size of u32 for Conn Type, Device Role and R flag + Dur + Rsvd*/
   1030     int ret = sizeof(u32);
   1031     /* size of availability interval bit map is 4 bytes */
   1032     ret += sizeof(u32);
   1033     /* size of mac address is 6 bytes*/
   1034     ret += (SIZEOF_TLV_HDR + NAN_MAC_ADDR_LEN);
   1035     if (pPostDiscovery &&
   1036         pPostDiscovery->type == NAN_CONN_WLAN_MESH) {
   1037         /* size of WLAN_MESH_ID  */
   1038         ret += (SIZEOF_TLV_HDR + \
   1039                 pPostDiscovery->mesh_id_len);
   1040     }
   1041     if (pPostDiscovery &&
   1042         pPostDiscovery->type == NAN_CONN_WLAN_INFRA) {
   1043         /* size of Infrastructure ssid  */
   1044         ret += (SIZEOF_TLV_HDR + \
   1045                 pPostDiscovery->infrastructure_ssid_len);
   1046     }
   1047     ALOGV("%s:size:%d", __func__, ret);
   1048     return ret;
   1049 }
   1050 
   1051 void NanCommand::fillNanSocialChannelParamVal(
   1052     const NanSocialChannelScanParams *pScanParams,
   1053     u32* pChannelParamArr)
   1054 {
   1055     int i;
   1056     if (pChannelParamArr) {
   1057         memset(pChannelParamArr, 0,
   1058                NAN_MAX_SOCIAL_CHANNELS * sizeof(u32));
   1059         for (i= 0; i < NAN_MAX_SOCIAL_CHANNELS; i++) {
   1060             pChannelParamArr[i] = pScanParams->scan_period[i] << 16;
   1061             pChannelParamArr[i] |= pScanParams->dwell_time[i] << 8;
   1062         }
   1063         pChannelParamArr[NAN_CHANNEL_24G_BAND] |= 6;
   1064         pChannelParamArr[NAN_CHANNEL_5G_BAND_LOW]|= 44;
   1065         pChannelParamArr[NAN_CHANNEL_5G_BAND_HIGH]|= 149;
   1066         ALOGV("%s: Filled SocialChannelParamVal", __func__);
   1067         hexdump((char*)pChannelParamArr, NAN_MAX_SOCIAL_CHANNELS * sizeof(u32));
   1068     }
   1069     return;
   1070 }
   1071 
   1072 u32 NanCommand::getNanTransmitPostConnectivityCapabilityVal(
   1073     const NanTransmitPostConnectivityCapability *pCapab)
   1074 {
   1075     u32 ret = 0;
   1076     ret |= (pCapab->payload_transmit_flag? 1:0) << 16;
   1077     ret |= (pCapab->is_mesh_supported? 1:0) << 5;
   1078     ret |= (pCapab->is_ibss_supported? 1:0) << 4;
   1079     ret |= (pCapab->wlan_infra_field? 1:0) << 3;
   1080     ret |= (pCapab->is_tdls_supported? 1:0) << 2;
   1081     ret |= (pCapab->is_wfds_supported? 1:0) << 1;
   1082     ret |= (pCapab->is_wfd_supported? 1:0);
   1083     ALOGV("%s: val:%d", __func__, ret);
   1084     return ret;
   1085 }
   1086 
   1087 void NanCommand::fillNanTransmitPostDiscoveryVal(
   1088     const NanTransmitPostDiscovery *pTxDisc,
   1089     u8 *pOutValue)
   1090 {
   1091 
   1092     if (pTxDisc && pOutValue) {
   1093         u8 *tlvs = &pOutValue[8];
   1094         pOutValue[0] = pTxDisc->type;
   1095         pOutValue[1] = pTxDisc->role;
   1096         pOutValue[2] = (pTxDisc->transmit_freq? 1:0);
   1097         pOutValue[2] |= ((pTxDisc->duration & 0x03) << 1);
   1098         memcpy(&pOutValue[4], &pTxDisc->avail_interval_bitmap,
   1099                sizeof(pTxDisc->avail_interval_bitmap));
   1100         tlvs = addTlv(NAN_TLV_TYPE_MAC_ADDRESS,
   1101                     NAN_MAC_ADDR_LEN,
   1102                     (const u8*)&pTxDisc->addr[0],
   1103                     tlvs);
   1104         if (pTxDisc->type == NAN_CONN_WLAN_MESH) {
   1105             tlvs = addTlv(NAN_TLV_TYPE_WLAN_MESH_ID,
   1106                         pTxDisc->mesh_id_len,
   1107                         (const u8*)&pTxDisc->mesh_id[0],
   1108                         tlvs);
   1109         }
   1110         if (pTxDisc->type == NAN_CONN_WLAN_INFRA) {
   1111             tlvs = addTlv(NAN_TLV_TYPE_WLAN_INFRA_SSID,
   1112                         pTxDisc->infrastructure_ssid_len,
   1113                         (const u8*)&pTxDisc->infrastructure_ssid_val[0],
   1114                         tlvs);
   1115         }
   1116         ALOGV("%s: Filled TransmitPostDiscoveryVal", __func__);
   1117         hexdump((char*)pOutValue, calcNanTransmitPostDiscoverySize(pTxDisc));
   1118     }
   1119 
   1120     return;
   1121 }
   1122 
   1123 void NanCommand::fillNanFurtherAvailabilityMapVal(
   1124     const NanFurtherAvailabilityMap *pFam,
   1125     u8 *pOutValue)
   1126 {
   1127     int idx = 0;
   1128 
   1129     if (pFam && pOutValue) {
   1130         u32 famsize = calcNanFurtherAvailabilityMapSize(pFam);
   1131         pNanFurtherAvailabilityMapAttrTlv pFwReq = \
   1132             (pNanFurtherAvailabilityMapAttrTlv)pOutValue;
   1133 
   1134         memset(pOutValue, 0, famsize);
   1135         pFwReq->numChan = pFam->numchans;
   1136         for (idx = 0; idx < pFam->numchans; idx++) {
   1137             const NanFurtherAvailabilityChannel *pFamChan =  \
   1138                 &pFam->famchan[idx];
   1139             pNanFurtherAvailabilityChan pFwFamChan = \
   1140                 (pNanFurtherAvailabilityChan)((u8*)&pFwReq->pFaChan[0] + \
   1141                 (idx * sizeof(NanFurtherAvailabilityChan)));
   1142 
   1143             pFwFamChan->entryCtrl.availIntDuration = \
   1144                 pFamChan->entry_control;
   1145             pFwFamChan->entryCtrl.mapId = \
   1146                 pFamChan->mapid;
   1147             pFwFamChan->opClass =  pFamChan->class_val;
   1148             pFwFamChan->channel = pFamChan->channel;
   1149             memcpy(&pFwFamChan->availIntBitmap,
   1150                    &pFamChan->avail_interval_bitmap,
   1151                    sizeof(pFwFamChan->availIntBitmap));
   1152         }
   1153         ALOGV("%s: Filled FurtherAvailabilityMapVal", __func__);
   1154         hexdump((char*)pOutValue, famsize);
   1155     }
   1156     return;
   1157 }
   1158 
   1159 int NanCommand::calcNanFurtherAvailabilityMapSize(
   1160     const NanFurtherAvailabilityMap *pFam)
   1161 {
   1162     int ret = 0;
   1163     if (pFam && pFam->numchans &&
   1164         pFam->numchans <= NAN_MAX_FAM_CHANNELS) {
   1165         /* Fixed size of u8 for numchans*/
   1166         ret = sizeof(u8);
   1167         /* numchans * sizeof(FamChannels) */
   1168         ret += (pFam->numchans * sizeof(NanFurtherAvailabilityChan));
   1169     }
   1170     ALOGV("%s:size:%d", __func__, ret);
   1171     return ret;
   1172 }
   1173 
   1174 int NanCommand::putNanCapabilities(transaction_id id)
   1175 {
   1176     size_t message_len = sizeof(NanCapabilitiesReqMsg);
   1177 
   1178     pNanCapabilitiesReqMsg pFwReq = (pNanCapabilitiesReqMsg)malloc(message_len);
   1179     if (pFwReq == NULL) {
   1180         cleanup();
   1181         return WIFI_ERROR_OUT_OF_MEMORY;
   1182     }
   1183 
   1184     memset (pFwReq, 0, message_len);
   1185     pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
   1186     pFwReq->fwHeader.msgId = NAN_MSG_ID_CAPABILITIES_REQ;
   1187     pFwReq->fwHeader.msgLen = message_len;
   1188     pFwReq->fwHeader.transactionId = id;
   1189 
   1190     mVendorData = (char*)pFwReq;
   1191     mDataLen = message_len;
   1192 
   1193     int ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
   1194     if (ret < 0) {
   1195         ALOGE("%s: put_bytes Error:%d",__func__, ret);
   1196         cleanup();
   1197         return ret;
   1198     }
   1199     hexdump(mVendorData, mDataLen);
   1200     return ret;
   1201 }
   1202