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  * Changes from Qualcomm Innovation Center are provided under the following license:
17  *
18  * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
19  *
20  * Redistribution and use in source and binary forms, with or without
21  * modification, are permitted (subject to the limitations in the
22  * disclaimer below) provided that the following conditions are met:
23  *
24  *   * Redistributions of source code must retain the above copyright
25  *     notice, this list of conditions and the following disclaimer.
26  *
27  *   * Redistributions in binary form must reproduce the above
28  *     copyright notice, this list of conditions and the following
29  *     disclaimer in the documentation and/or other materials provided
30  *     with the distribution.
31  *
32  *   * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
33  *     contributors may be used to endorse or promote products derived
34  *     from this software without specific prior written permission.
35  *
36  * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
37  * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
38  * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
39  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
40  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
41  * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
42  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
43  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
44  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
45  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
46  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
47  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
48  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
49  */
50 
51 #include "sync.h"
52 #include <utils/Log.h>
53 #include <hardware_legacy/wifi_hal.h>
54 #include "nan_i.h"
55 #include "nancommand.h"
56 
putNanEnable(transaction_id id,const NanEnableRequest * pReq)57 wifi_error NanCommand::putNanEnable(transaction_id id, const NanEnableRequest *pReq)
58 {
59     wifi_error ret;
60     ALOGV("NAN_ENABLE");
61     size_t message_len = NAN_MAX_ENABLE_REQ_SIZE;
62     int freq_24g;
63 
64     if (pReq == NULL) {
65         cleanup();
66         return WIFI_ERROR_INVALID_ARGS;
67     }
68 
69     if (pReq->config_24g_channel == 0)
70         freq_24g = 2437;
71     else
72         freq_24g = pReq->channel_24g_val;
73 
74     message_len += \
75         (
76           pReq->config_support_5g ? (SIZEOF_TLV_HDR + \
77           sizeof(pReq->support_5g_val)) : 0 \
78         ) + \
79         (
80           pReq->config_sid_beacon ? (SIZEOF_TLV_HDR + \
81           sizeof(pReq->sid_beacon_val)) : 0 \
82         ) + \
83         (
84           pReq->config_2dot4g_rssi_close ? (SIZEOF_TLV_HDR + \
85           sizeof(pReq->rssi_close_2dot4g_val)) : 0 \
86         ) + \
87         (
88           pReq->config_2dot4g_rssi_middle ? (SIZEOF_TLV_HDR + \
89           sizeof(pReq->rssi_middle_2dot4g_val)) : 0 \
90         ) + \
91         (
92           pReq->config_hop_count_limit ? (SIZEOF_TLV_HDR + \
93           sizeof(pReq->hop_count_limit_val)) : 0 \
94         ) + \
95         (
96           pReq->config_2dot4g_support ? (SIZEOF_TLV_HDR + \
97           sizeof(pReq->support_2dot4g_val)) : 0 \
98         ) + \
99         (
100           pReq->config_2dot4g_beacons ? (SIZEOF_TLV_HDR + \
101           sizeof(pReq->beacon_2dot4g_val)) : 0 \
102         ) + \
103         (
104           pReq->config_2dot4g_sdf ? (SIZEOF_TLV_HDR + \
105           sizeof(pReq->sdf_2dot4g_val)) : 0 \
106         ) + \
107         (
108           pReq->config_5g_beacons ? (SIZEOF_TLV_HDR + \
109           sizeof(pReq->beacon_5g_val)) : 0 \
110         ) + \
111         (
112           pReq->config_5g_sdf ? (SIZEOF_TLV_HDR + \
113           sizeof(pReq->sdf_5g_val)) : 0 \
114         ) + \
115         (
116           pReq->config_5g_rssi_close ? (SIZEOF_TLV_HDR + \
117           sizeof(pReq->rssi_close_5g_val)) : 0 \
118         ) + \
119         (
120           pReq->config_5g_rssi_middle ? (SIZEOF_TLV_HDR + \
121           sizeof(pReq->rssi_middle_5g_val)) : 0 \
122         ) + \
123         (
124           pReq->config_2dot4g_rssi_proximity ? (SIZEOF_TLV_HDR + \
125           sizeof(pReq->rssi_proximity_2dot4g_val)) : 0 \
126         ) + \
127         (
128           pReq->config_5g_rssi_close_proximity ? (SIZEOF_TLV_HDR + \
129           sizeof(pReq->rssi_close_proximity_5g_val)) : 0 \
130         ) + \
131         (
132           pReq->config_rssi_window_size ? (SIZEOF_TLV_HDR + \
133           sizeof(pReq->rssi_window_size_val)) : 0 \
134         ) + \
135         (
136           pReq->config_oui ? (SIZEOF_TLV_HDR + \
137           sizeof(pReq->oui_val)) : 0 \
138         ) + \
139         (
140           pReq->config_intf_addr ? (SIZEOF_TLV_HDR + \
141           sizeof(pReq->intf_addr_val)) : 0 \
142         ) + \
143         (
144           pReq->config_cluster_attribute_val ? (SIZEOF_TLV_HDR + \
145           sizeof(pReq->config_cluster_attribute_val)) : 0 \
146         ) + \
147         (
148           pReq->config_scan_params ? NAN_MAX_SOCIAL_CHANNELS *
149           (SIZEOF_TLV_HDR + sizeof(u32)) : 0 \
150         ) + \
151         (
152           pReq->config_random_factor_force ? (SIZEOF_TLV_HDR + \
153           sizeof(pReq->random_factor_force_val)) : 0 \
154         ) + \
155         (
156           pReq->config_hop_count_force ? (SIZEOF_TLV_HDR + \
157           sizeof(pReq->hop_count_force_val)) : 0 \
158         ) + \
159         (
160           /* always include 24g channel/freq */
161           SIZEOF_TLV_HDR +  sizeof(u32) \
162         ) + \
163         (
164           pReq->config_5g_channel ? (SIZEOF_TLV_HDR + \
165           sizeof(u32)) : 0 \
166         ) + \
167         (
168            pReq->config_dw.config_2dot4g_dw_band ? (SIZEOF_TLV_HDR + \
169            sizeof(u32)) : 0 \
170         ) + \
171         (
172            pReq->config_dw.config_5g_dw_band ? (SIZEOF_TLV_HDR + \
173            sizeof(u32)) : 0 \
174         ) + \
175         (
176            pReq->config_disc_mac_addr_randomization ? (SIZEOF_TLV_HDR + \
177            sizeof(u32)) : 0 \
178         ) + \
179         (
180            /* Always include cfg discovery indication TLV */
181            SIZEOF_TLV_HDR + sizeof(u32) \
182         ) + \
183         (
184           pReq->config_subscribe_sid_beacon ? (SIZEOF_TLV_HDR + \
185           sizeof(pReq->subscribe_sid_beacon_val)) : 0 \
186         ) + \
187         (
188            pReq->config_discovery_beacon_int ? (SIZEOF_TLV_HDR + \
189            sizeof(u32)) : 0 \
190         ) + \
191         (
192            pReq->config_nss ? (SIZEOF_TLV_HDR + \
193            sizeof(u32)) : 0 \
194         ) + \
195         (
196            pReq->config_enable_ranging ? (SIZEOF_TLV_HDR + \
197            sizeof(u32)) : 0 \
198         ) + \
199         (
200            pReq->config_dw_early_termination ? (SIZEOF_TLV_HDR + \
201            sizeof(u32)) : 0 \
202         );
203 
204     pNanEnableReqMsg pFwReq = (pNanEnableReqMsg)malloc(message_len);
205     if (pFwReq == NULL) {
206         cleanup();
207         return WIFI_ERROR_OUT_OF_MEMORY;
208     }
209 
210     ALOGV("Message Len %zu", message_len);
211     memset (pFwReq, 0, message_len);
212     pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
213     pFwReq->fwHeader.msgId = NAN_MSG_ID_ENABLE_REQ;
214     pFwReq->fwHeader.msgLen = message_len;
215     pFwReq->fwHeader.transactionId = id;
216 
217     u8* tlvs = pFwReq->ptlv;
218 
219     /* Write the TLVs to the message. */
220 
221     tlvs = addTlv(NAN_TLV_TYPE_CLUSTER_ID_LOW, sizeof(pReq->cluster_low),
222                   (const u8*)&pReq->cluster_low, tlvs);
223     tlvs = addTlv(NAN_TLV_TYPE_CLUSTER_ID_HIGH, sizeof(pReq->cluster_high),
224                   (const u8*)&pReq->cluster_high, tlvs);
225     tlvs = addTlv(NAN_TLV_TYPE_MASTER_PREFERENCE, sizeof(pReq->master_pref),
226                   (const u8*)&pReq->master_pref, tlvs);
227     if (pReq->config_support_5g) {
228         tlvs = addTlv(NAN_TLV_TYPE_5G_SUPPORT, sizeof(pReq->support_5g_val),
229                      (const u8*)&pReq->support_5g_val, tlvs);
230     }
231     if (pReq->config_sid_beacon) {
232         tlvs = addTlv(NAN_TLV_TYPE_SID_BEACON, sizeof(pReq->sid_beacon_val),
233                       (const u8*)&pReq->sid_beacon_val, tlvs);
234     }
235     if (pReq->config_2dot4g_rssi_close) {
236         tlvs = addTlv(NAN_TLV_TYPE_24G_RSSI_CLOSE,
237                       sizeof(pReq->rssi_close_2dot4g_val),
238                       (const u8*)&pReq->rssi_close_2dot4g_val, tlvs);
239     }
240     if (pReq->config_2dot4g_rssi_middle) {
241         tlvs = addTlv(NAN_TLV_TYPE_24G_RSSI_MIDDLE,
242                       sizeof(pReq->rssi_middle_2dot4g_val),
243                       (const u8*)&pReq->rssi_middle_2dot4g_val, tlvs);
244     }
245     if (pReq->config_hop_count_limit) {
246         tlvs = addTlv(NAN_TLV_TYPE_HOP_COUNT_LIMIT,
247                       sizeof(pReq->hop_count_limit_val),
248                       (const u8*)&pReq->hop_count_limit_val, tlvs);
249     }
250     if (pReq->config_2dot4g_support) {
251         tlvs = addTlv(NAN_TLV_TYPE_24G_SUPPORT, sizeof(pReq->support_2dot4g_val),
252                       (const u8*)&pReq->support_2dot4g_val, tlvs);
253     }
254     if (pReq->config_2dot4g_beacons) {
255         tlvs = addTlv(NAN_TLV_TYPE_24G_BEACON, sizeof(pReq->beacon_2dot4g_val),
256                       (const u8*)&pReq->beacon_2dot4g_val, tlvs);
257     }
258     if (pReq->config_2dot4g_sdf) {
259         tlvs = addTlv(NAN_TLV_TYPE_24G_SDF, sizeof(pReq->sdf_2dot4g_val),
260                       (const u8*)&pReq->sdf_2dot4g_val, tlvs);
261     }
262     if (pReq->config_5g_beacons) {
263         tlvs = addTlv(NAN_TLV_TYPE_5G_BEACON, sizeof(pReq->beacon_5g_val),
264                       (const u8*)&pReq->beacon_5g_val, tlvs);
265     }
266     if (pReq->config_5g_sdf) {
267         tlvs = addTlv(NAN_TLV_TYPE_5G_SDF, sizeof(pReq->sdf_5g_val),
268                       (const u8*)&pReq->sdf_5g_val, tlvs);
269     }
270     if (pReq->config_2dot4g_rssi_proximity) {
271         tlvs = addTlv(NAN_TLV_TYPE_24G_RSSI_CLOSE_PROXIMITY,
272                       sizeof(pReq->rssi_proximity_2dot4g_val),
273                       (const u8*)&pReq->rssi_proximity_2dot4g_val, tlvs);
274     }
275     /* Add the support of sending 5G RSSI values */
276     if (pReq->config_5g_rssi_close) {
277         tlvs = addTlv(NAN_TLV_TYPE_5G_RSSI_CLOSE, sizeof(pReq->rssi_close_5g_val),
278                       (const u8*)&pReq->rssi_close_5g_val, tlvs);
279     }
280     if (pReq->config_5g_rssi_middle) {
281         tlvs = addTlv(NAN_TLV_TYPE_5G_RSSI_MIDDLE, sizeof(pReq->rssi_middle_5g_val),
282                       (const u8*)&pReq->rssi_middle_5g_val, tlvs);
283     }
284     if (pReq->config_5g_rssi_close_proximity) {
285         tlvs = addTlv(NAN_TLV_TYPE_5G_RSSI_CLOSE_PROXIMITY,
286                       sizeof(pReq->rssi_close_proximity_5g_val),
287                       (const u8*)&pReq->rssi_close_proximity_5g_val, tlvs);
288     }
289     if (pReq->config_rssi_window_size) {
290         tlvs = addTlv(NAN_TLV_TYPE_RSSI_AVERAGING_WINDOW_SIZE, sizeof(pReq->rssi_window_size_val),
291                       (const u8*)&pReq->rssi_window_size_val, tlvs);
292     }
293     if (pReq->config_oui) {
294         tlvs = addTlv(NAN_TLV_TYPE_CLUSTER_OUI_NETWORK_ID, sizeof(pReq->oui_val),
295                       (const u8*)&pReq->oui_val, tlvs);
296     }
297     if (pReq->config_intf_addr) {
298         tlvs = addTlv(NAN_TLV_TYPE_SOURCE_MAC_ADDRESS, sizeof(pReq->intf_addr_val),
299                       (const u8*)&pReq->intf_addr_val[0], tlvs);
300     }
301     if (pReq->config_cluster_attribute_val) {
302         tlvs = addTlv(NAN_TLV_TYPE_CLUSTER_ATTRIBUTE_IN_SDF, sizeof(pReq->config_cluster_attribute_val),
303                       (const u8*)&pReq->config_cluster_attribute_val, tlvs);
304     }
305     if (pReq->config_scan_params) {
306         u32 socialChannelParamVal[NAN_MAX_SOCIAL_CHANNELS];
307         /* Fill the social channel param */
308         fillNanSocialChannelParamVal(&pReq->scan_params_val,
309                                      socialChannelParamVal);
310         int i;
311         for (i = 0; i < NAN_MAX_SOCIAL_CHANNELS; i++) {
312             tlvs = addTlv(NAN_TLV_TYPE_SOCIAL_CHANNEL_SCAN_PARAMS,
313                           sizeof(socialChannelParamVal[i]),
314                           (const u8*)&socialChannelParamVal[i], tlvs);
315         }
316     }
317     if (pReq->config_random_factor_force) {
318         tlvs = addTlv(NAN_TLV_TYPE_RANDOM_FACTOR_FORCE,
319                       sizeof(pReq->random_factor_force_val),
320                       (const u8*)&pReq->random_factor_force_val, tlvs);
321     }
322     if (pReq->config_hop_count_force) {
323         tlvs = addTlv(NAN_TLV_TYPE_HOP_COUNT_FORCE,
324                       sizeof(pReq->hop_count_force_val),
325                       (const u8*)&pReq->hop_count_force_val, tlvs);
326     }
327     tlvs = addTlv(NAN_TLV_TYPE_24G_CHANNEL,
328                       sizeof(u32),
329                       (const u8*)&freq_24g, tlvs);
330     if (pReq->config_5g_channel) {
331         tlvs = addTlv(NAN_TLV_TYPE_5G_CHANNEL,
332                       sizeof(u32),
333                       (const u8*)&pReq->channel_5g_val, tlvs);
334     }
335     if (pReq->config_dw.config_2dot4g_dw_band) {
336         tlvs = addTlv(NAN_TLV_TYPE_2G_COMMITTED_DW,
337                       sizeof(pReq->config_dw.dw_2dot4g_interval_val),
338                       (const u8*)&pReq->config_dw.dw_2dot4g_interval_val, tlvs);
339     }
340     if (pReq->config_dw.config_5g_dw_band) {
341         tlvs = addTlv(NAN_TLV_TYPE_5G_COMMITTED_DW,
342                       sizeof(pReq->config_dw.dw_5g_interval_val),
343                       (const u8*)&pReq->config_dw.dw_5g_interval_val, tlvs);
344     }
345     if (pReq->config_disc_mac_addr_randomization) {
346         tlvs = addTlv(NAN_TLV_TYPE_DISC_MAC_ADDR_RANDOM_INTERVAL,
347                       sizeof(u32),
348                       (const u8*)&pReq->disc_mac_addr_rand_interval_sec, tlvs);
349     }
350 
351     u32 config_discovery_indications;
352     config_discovery_indications = (u32)pReq->discovery_indication_cfg;
353     /* Save the discovery MAC indication config if it is disabled from the
354      * framework and use it later to decide if the framework to be notified of
355      * the response. And enable the self MAC discovery indication from firmware
356      * by resetting the bit in config to get the Self MAC.
357      */
358     if (config_discovery_indications & NAN_DISC_ADDR_IND_DISABLED) {
359         mNanCommandInstance->mNanDiscAddrIndDisabled = true;
360         config_discovery_indications &= ~NAN_DISC_ADDR_IND_DISABLED;
361     } else {
362         mNanCommandInstance->mNanDiscAddrIndDisabled = false;
363     }
364     tlvs = addTlv(NAN_TLV_TYPE_CONFIG_DISCOVERY_INDICATIONS,
365                   sizeof(u32),
366                   (const u8*)&config_discovery_indications, tlvs);
367 
368     if (pReq->config_subscribe_sid_beacon) {
369         tlvs = addTlv(NAN_TLV_TYPE_SUBSCRIBE_SID_BEACON,
370                       sizeof(pReq->subscribe_sid_beacon_val),
371                       (const u8*)&pReq->subscribe_sid_beacon_val, tlvs);
372     }
373     if (pReq->config_discovery_beacon_int) {
374         tlvs = addTlv(NAN_TLV_TYPE_DB_INTERVAL, sizeof(u32),
375                       (const u8*)&pReq->discovery_beacon_interval, tlvs);
376     }
377     if (pReq->config_nss) {
378         tlvs = addTlv(NAN_TLV_TYPE_TX_RX_CHAINS, sizeof(u32),
379                       (const u8*)&pReq->nss, tlvs);
380     }
381     if (pReq->config_enable_ranging) {
382         tlvs = addTlv(NAN_TLV_TYPE_ENABLE_DEVICE_RANGING, sizeof(u32),
383                       (const u8*)&pReq->enable_ranging, tlvs);
384     }
385     if (pReq->config_dw_early_termination) {
386         tlvs = addTlv(NAN_TLV_TYPE_DW_EARLY_TERMINATION, sizeof(u32),
387                       (const u8*)&pReq->enable_dw_termination, tlvs);
388     }
389 
390     mVendorData = (char*)pFwReq;
391     mDataLen = message_len;
392 
393     ret = WIFI_SUCCESS;
394     if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
395         //Insert the vendor specific data
396         ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
397         if (ret != WIFI_SUCCESS) {
398             ALOGE("%s: put_bytes Error:%d",__func__, ret);
399             cleanup();
400             return ret;
401         }
402     } else {
403         struct nlattr *nl_data;
404 
405         nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
406         if (!nl_data) {
407             cleanup();
408             return WIFI_ERROR_INVALID_ARGS;
409         }
410         if (mMsg.put_u32(QCA_WLAN_VENDOR_ATTR_NAN_SUBCMD_TYPE,
411                            QCA_WLAN_NAN_EXT_SUBCMD_TYPE_ENABLE_REQ) ||
412             mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
413                              mVendorData, mDataLen)) {
414             ALOGE("%s: put attr error", __func__);
415             cleanup();
416             return WIFI_ERROR_INVALID_ARGS;
417         }
418 
419         if (mMsg.put_u32(QCA_WLAN_VENDOR_ATTR_NAN_DISC_24GHZ_BAND_FREQ,
420                            freq_24g)) {
421             ALOGE("%s: put attr error", __func__);
422             cleanup();
423             return WIFI_ERROR_INVALID_ARGS;
424         }
425 
426         if (pReq->config_5g_channel) {
427             if (mMsg.put_u32(QCA_WLAN_VENDOR_ATTR_NAN_DISC_5GHZ_BAND_FREQ,
428                                pReq->channel_5g_val)) {
429                 ALOGE("%s: put attr error", __func__);
430                 cleanup();
431                 return WIFI_ERROR_INVALID_ARGS;
432             }
433         }
434         attr_end(nl_data);
435     }
436     hexdump(mVendorData, mDataLen);
437     return ret;
438 }
439 
putNanDisable(transaction_id id)440 wifi_error NanCommand::putNanDisable(transaction_id id)
441 {
442     wifi_error ret;
443     ALOGV("NAN_DISABLE");
444     size_t message_len = sizeof(NanDisableReqMsg);
445 
446     pNanDisableReqMsg pFwReq = (pNanDisableReqMsg)malloc(message_len);
447     if (pFwReq == NULL) {
448         cleanup();
449         return WIFI_ERROR_OUT_OF_MEMORY;
450     }
451 
452     ALOGV("Message Len %zu", message_len);
453     memset (pFwReq, 0, message_len);
454     pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
455     pFwReq->fwHeader.msgId = NAN_MSG_ID_DISABLE_REQ;
456     pFwReq->fwHeader.msgLen = message_len;
457     pFwReq->fwHeader.transactionId = id;
458 
459     mVendorData = (char*)pFwReq;
460     mDataLen = message_len;
461 
462     ret = WIFI_SUCCESS;
463     if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
464         ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
465         if (ret != WIFI_SUCCESS) {
466             ALOGE("%s: put_bytes Error:%d",__func__, ret);
467             cleanup();
468             return ret;
469         }
470     } else {
471         struct nlattr *nl_data;
472 
473         nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
474         if (!nl_data) {
475             cleanup();
476             return WIFI_ERROR_INVALID_ARGS;
477         }
478 
479         if (mMsg.put_u32(QCA_WLAN_VENDOR_ATTR_NAN_SUBCMD_TYPE,
480                            QCA_WLAN_NAN_EXT_SUBCMD_TYPE_DISABLE_REQ) ||
481             mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
482                              mVendorData, mDataLen)) {
483             ALOGE("%s: put attr error", __func__);
484             cleanup();
485             return WIFI_ERROR_INVALID_ARGS;
486         }
487         attr_end(nl_data);
488     }
489     hexdump(mVendorData, mDataLen);
490     return ret;
491 }
492 
putNanConfig(transaction_id id,const NanConfigRequest * pReq)493 wifi_error NanCommand::putNanConfig(transaction_id id, const NanConfigRequest *pReq)
494 {
495     wifi_error ret;
496     ALOGV("NAN_CONFIG");
497     size_t message_len = 0;
498     int idx = 0;
499 
500     if (pReq == NULL ||
501         pReq->num_config_discovery_attr > NAN_MAX_POSTDISCOVERY_LEN) {
502         cleanup();
503         return WIFI_ERROR_INVALID_ARGS;
504     }
505 
506     message_len = sizeof(NanMsgHeader);
507 
508     message_len += \
509         (
510            pReq->config_sid_beacon ? (SIZEOF_TLV_HDR + \
511            sizeof(pReq->sid_beacon)) : 0 \
512         ) + \
513         (
514            pReq->config_master_pref ? (SIZEOF_TLV_HDR + \
515            sizeof(pReq->master_pref)) : 0 \
516         ) + \
517         (
518            pReq->config_rssi_proximity ? (SIZEOF_TLV_HDR + \
519            sizeof(pReq->rssi_proximity)) : 0 \
520         ) + \
521         (
522            pReq->config_5g_rssi_close_proximity ? (SIZEOF_TLV_HDR + \
523            sizeof(pReq->rssi_close_proximity_5g_val)) : 0 \
524         ) + \
525         (
526            pReq->config_rssi_window_size ? (SIZEOF_TLV_HDR + \
527            sizeof(pReq->rssi_window_size_val)) : 0 \
528         ) + \
529         (
530            pReq->config_cluster_attribute_val ? (SIZEOF_TLV_HDR + \
531            sizeof(pReq->config_cluster_attribute_val)) : 0 \
532         ) + \
533         (
534            pReq->config_scan_params ? NAN_MAX_SOCIAL_CHANNELS *
535            (SIZEOF_TLV_HDR + sizeof(u32)) : 0 \
536         ) + \
537         (
538            pReq->config_random_factor_force ? (SIZEOF_TLV_HDR + \
539            sizeof(pReq->random_factor_force_val)) : 0 \
540         ) + \
541         (
542            pReq->config_hop_count_force ? (SIZEOF_TLV_HDR + \
543            sizeof(pReq->hop_count_force_val)) : 0 \
544         ) + \
545         (
546            pReq->config_conn_capability ? (SIZEOF_TLV_HDR + \
547            sizeof(u32)) : 0 \
548         ) + \
549         (
550            pReq->config_dw.config_2dot4g_dw_band ? (SIZEOF_TLV_HDR + \
551            sizeof(u32)) : 0 \
552         ) + \
553         (
554            pReq->config_dw.config_5g_dw_band ? (SIZEOF_TLV_HDR + \
555            sizeof(u32)) : 0 \
556         ) + \
557         (
558            pReq->config_disc_mac_addr_randomization ? (SIZEOF_TLV_HDR + \
559            sizeof(u32)) : 0 \
560         ) + \
561         (
562           pReq->config_subscribe_sid_beacon ? (SIZEOF_TLV_HDR + \
563           sizeof(pReq->subscribe_sid_beacon_val)) : 0 \
564         ) + \
565         (
566            /* Always include cfg discovery indication TLV */
567            SIZEOF_TLV_HDR + sizeof(u32) \
568         ) + \
569         (
570            pReq->config_discovery_beacon_int ? (SIZEOF_TLV_HDR + \
571            sizeof(u32)) : 0 \
572         ) + \
573         (
574            pReq->config_nss ? (SIZEOF_TLV_HDR + \
575            sizeof(u32)) : 0 \
576         ) + \
577         (
578            pReq->config_enable_ranging ? (SIZEOF_TLV_HDR + \
579            sizeof(u32)) : 0 \
580         ) + \
581         (
582            pReq->config_dw_early_termination ? (SIZEOF_TLV_HDR + \
583            sizeof(u32)) : 0 \
584         );
585 
586     if (pReq->num_config_discovery_attr) {
587         for (idx = 0; idx < pReq->num_config_discovery_attr; idx ++) {
588             message_len += SIZEOF_TLV_HDR +\
589                 calcNanTransmitPostDiscoverySize(&pReq->discovery_attr_val[idx]);
590         }
591     }
592 
593     if (pReq->config_fam && \
594         calcNanFurtherAvailabilityMapSize(&pReq->fam_val)) {
595         message_len += (SIZEOF_TLV_HDR + \
596            calcNanFurtherAvailabilityMapSize(&pReq->fam_val));
597     }
598 
599     pNanConfigurationReqMsg pFwReq = (pNanConfigurationReqMsg)malloc(message_len);
600     if (pFwReq == NULL) {
601         cleanup();
602         return WIFI_ERROR_OUT_OF_MEMORY;
603     }
604 
605     ALOGV("Message Len %zu", message_len);
606     memset (pFwReq, 0, message_len);
607     pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
608     pFwReq->fwHeader.msgId = NAN_MSG_ID_CONFIGURATION_REQ;
609     pFwReq->fwHeader.msgLen = message_len;
610     pFwReq->fwHeader.transactionId = id;
611 
612     u8* tlvs = pFwReq->ptlv;
613     if (pReq->config_sid_beacon) {
614         tlvs = addTlv(NAN_TLV_TYPE_SID_BEACON, sizeof(pReq->sid_beacon),
615                       (const u8*)&pReq->sid_beacon, tlvs);
616     }
617     if (pReq->config_master_pref) {
618         tlvs = addTlv(NAN_TLV_TYPE_MASTER_PREFERENCE, sizeof(pReq->master_pref),
619                       (const u8*)&pReq->master_pref, tlvs);
620     }
621     if (pReq->config_rssi_window_size) {
622         tlvs = addTlv(NAN_TLV_TYPE_RSSI_AVERAGING_WINDOW_SIZE, sizeof(pReq->rssi_window_size_val),
623                       (const u8*)&pReq->rssi_window_size_val, tlvs);
624     }
625     if (pReq->config_rssi_proximity) {
626         tlvs = addTlv(NAN_TLV_TYPE_24G_RSSI_CLOSE_PROXIMITY, sizeof(pReq->rssi_proximity),
627                       (const u8*)&pReq->rssi_proximity, tlvs);
628     }
629     if (pReq->config_5g_rssi_close_proximity) {
630         tlvs = addTlv(NAN_TLV_TYPE_5G_RSSI_CLOSE_PROXIMITY,
631                       sizeof(pReq->rssi_close_proximity_5g_val),
632                       (const u8*)&pReq->rssi_close_proximity_5g_val, tlvs);
633     }
634     if (pReq->config_cluster_attribute_val) {
635         tlvs = addTlv(NAN_TLV_TYPE_CLUSTER_ATTRIBUTE_IN_SDF, sizeof(pReq->config_cluster_attribute_val),
636                       (const u8*)&pReq->config_cluster_attribute_val, tlvs);
637     }
638     if (pReq->config_scan_params) {
639         u32 socialChannelParamVal[NAN_MAX_SOCIAL_CHANNELS];
640         /* Fill the social channel param */
641         fillNanSocialChannelParamVal(&pReq->scan_params_val,
642                                  socialChannelParamVal);
643         int i;
644         for (i = 0; i < NAN_MAX_SOCIAL_CHANNELS; i++) {
645             tlvs = addTlv(NAN_TLV_TYPE_SOCIAL_CHANNEL_SCAN_PARAMS,
646                           sizeof(socialChannelParamVal[i]),
647                           (const u8*)&socialChannelParamVal[i], tlvs);
648         }
649     }
650     if (pReq->config_random_factor_force) {
651         tlvs = addTlv(NAN_TLV_TYPE_RANDOM_FACTOR_FORCE,
652                       sizeof(pReq->random_factor_force_val),
653                       (const u8*)&pReq->random_factor_force_val, tlvs);
654     }
655     if (pReq->config_hop_count_force) {
656         tlvs = addTlv(NAN_TLV_TYPE_HOP_COUNT_FORCE,
657                       sizeof(pReq->hop_count_force_val),
658                       (const u8*)&pReq->hop_count_force_val, tlvs);
659     }
660     if (pReq->config_conn_capability) {
661         u32 val = \
662         getNanTransmitPostConnectivityCapabilityVal(&pReq->conn_capability_val);
663         tlvs = addTlv(NAN_TLV_TYPE_POST_NAN_CONNECTIVITY_CAPABILITIES_TRANSMIT,
664                       sizeof(val), (const u8*)&val, tlvs);
665     }
666     if (pReq->num_config_discovery_attr) {
667         for (idx = 0; idx < pReq->num_config_discovery_attr; idx ++) {
668             fillNanTransmitPostDiscoveryVal(&pReq->discovery_attr_val[idx],
669                                             (u8*)(tlvs + SIZEOF_TLV_HDR));
670             tlvs = addTlv(NAN_TLV_TYPE_POST_NAN_DISCOVERY_ATTRIBUTE_TRANSMIT,
671                           calcNanTransmitPostDiscoverySize(
672                               &pReq->discovery_attr_val[idx]),
673                           (const u8*)(tlvs + SIZEOF_TLV_HDR), tlvs);
674         }
675     }
676     if (pReq->config_fam && \
677         calcNanFurtherAvailabilityMapSize(&pReq->fam_val)) {
678         fillNanFurtherAvailabilityMapVal(&pReq->fam_val,
679                                         (u8*)(tlvs + SIZEOF_TLV_HDR));
680         tlvs = addTlv(NAN_TLV_TYPE_FURTHER_AVAILABILITY_MAP,
681                       calcNanFurtherAvailabilityMapSize(&pReq->fam_val),
682                       (const u8*)(tlvs + SIZEOF_TLV_HDR), tlvs);
683     }
684     if (pReq->config_dw.config_2dot4g_dw_band) {
685         tlvs = addTlv(NAN_TLV_TYPE_2G_COMMITTED_DW,
686                       sizeof(pReq->config_dw.dw_2dot4g_interval_val),
687                       (const u8*)&pReq->config_dw.dw_2dot4g_interval_val, tlvs);
688     }
689     if (pReq->config_dw.config_5g_dw_band) {
690         tlvs = addTlv(NAN_TLV_TYPE_5G_COMMITTED_DW,
691                       sizeof(pReq->config_dw.dw_5g_interval_val),
692                       (const u8*)&pReq->config_dw.dw_5g_interval_val, tlvs);
693     }
694     if (pReq->config_disc_mac_addr_randomization) {
695         tlvs = addTlv(NAN_TLV_TYPE_DISC_MAC_ADDR_RANDOM_INTERVAL,
696                       sizeof(u32),
697                       (const u8*)&pReq->disc_mac_addr_rand_interval_sec, tlvs);
698     }
699     if (pReq->config_subscribe_sid_beacon) {
700         tlvs = addTlv(NAN_TLV_TYPE_SUBSCRIBE_SID_BEACON,
701                       sizeof(pReq->subscribe_sid_beacon_val),
702                       (const u8*)&pReq->subscribe_sid_beacon_val, tlvs);
703     }
704     if (pReq->config_discovery_beacon_int) {
705         tlvs = addTlv(NAN_TLV_TYPE_DB_INTERVAL, sizeof(u32),
706                       (const u8*)&pReq->discovery_beacon_interval, tlvs);
707     }
708 
709     u32 config_discovery_indications;
710     config_discovery_indications = (u32)(pReq->discovery_indication_cfg);
711     /* Save the discovery MAC indication config if it is disabled from the
712      * framework and use it later to decide if the framework to be notified of
713      * the response. And enable the self MAC discovery indication from firmware
714      * by resetting the bit in config to get the Self MAC.
715      */
716     if (config_discovery_indications & NAN_DISC_ADDR_IND_DISABLED) {
717         mNanCommandInstance->mNanDiscAddrIndDisabled = true;
718         config_discovery_indications &= ~NAN_DISC_ADDR_IND_DISABLED;
719     } else {
720         mNanCommandInstance->mNanDiscAddrIndDisabled = false;
721     }
722     /* Always include the discovery cfg TLV as there is no cfg flag */
723     tlvs = addTlv(NAN_TLV_TYPE_CONFIG_DISCOVERY_INDICATIONS,
724                   sizeof(u32),
725                   (const u8*)&config_discovery_indications, tlvs);
726 
727     if (pReq->config_nss) {
728         tlvs = addTlv(NAN_TLV_TYPE_TX_RX_CHAINS, sizeof(u32),
729                       (const u8*)&pReq->nss, tlvs);
730     }
731     if (pReq->config_enable_ranging) {
732         tlvs = addTlv(NAN_TLV_TYPE_ENABLE_DEVICE_RANGING, sizeof(u32),
733                       (const u8*)&pReq->enable_ranging, tlvs);
734     }
735     if (pReq->config_dw_early_termination) {
736         tlvs = addTlv(NAN_TLV_TYPE_DW_EARLY_TERMINATION, sizeof(u32),
737                       (const u8*)&pReq->enable_dw_termination, tlvs);
738     }
739 
740     mVendorData = (char*)pFwReq;
741     mDataLen = message_len;
742 
743     ret = WIFI_SUCCESS;
744     if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
745         ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
746         if (ret != WIFI_SUCCESS) {
747             ALOGE("%s: put_bytes Error:%d",__func__, ret);
748             cleanup();
749             return ret;
750         }
751     } else {
752         struct nlattr *nl_data;
753 
754         nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
755         if (!nl_data) {
756             cleanup();
757             return WIFI_ERROR_INVALID_ARGS;
758         }
759         if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
760                              mVendorData, mDataLen)) {
761             ALOGE("%s: put attr error", __func__);
762             cleanup();
763             return WIFI_ERROR_INVALID_ARGS;
764         }
765         attr_end(nl_data);
766     }
767     hexdump(mVendorData, mDataLen);
768     return ret;
769 }
770 
putNanPublish(transaction_id id,const NanPublishRequest * pReq)771 wifi_error NanCommand::putNanPublish(transaction_id id, const NanPublishRequest *pReq)
772 {
773     wifi_error ret;
774     ALOGV("NAN_PUBLISH");
775     if (pReq == NULL) {
776         cleanup();
777         return WIFI_ERROR_INVALID_ARGS;
778     }
779 
780     size_t message_len =
781         sizeof(NanMsgHeader) + sizeof(NanPublishServiceReqParams) +
782         (pReq->service_name_len ? SIZEOF_TLV_HDR + pReq->service_name_len : 0) +
783         (pReq->service_specific_info_len ? SIZEOF_TLV_HDR + pReq->service_specific_info_len : 0) +
784         (pReq->rx_match_filter_len ? SIZEOF_TLV_HDR + pReq->rx_match_filter_len : 0) +
785         (pReq->tx_match_filter_len ? SIZEOF_TLV_HDR + pReq->tx_match_filter_len : 0) +
786         (SIZEOF_TLV_HDR + sizeof(NanServiceAcceptPolicy)) +
787         (pReq->cipher_type ? SIZEOF_TLV_HDR + sizeof(NanCsidType) : 0) +
788         ((pReq->sdea_params.config_nan_data_path || pReq->sdea_params.security_cfg ||
789           pReq->sdea_params.ranging_state || pReq->sdea_params.range_report ||
790           pReq->sdea_params.qos_cfg) ?
791           SIZEOF_TLV_HDR + sizeof(NanFWSdeaCtrlParams) : 0) +
792         ((pReq->ranging_cfg.ranging_interval_msec || pReq->ranging_cfg.config_ranging_indications ||
793           pReq->ranging_cfg.distance_ingress_mm || pReq->ranging_cfg.distance_egress_mm) ?
794           SIZEOF_TLV_HDR + sizeof(NanFWRangeConfigParams) : 0) +
795         ((pReq->range_response_cfg.publish_id ||
796           pReq->range_response_cfg.ranging_response) ?
797           SIZEOF_TLV_HDR + sizeof(NanFWRangeReqMsg) : 0)  +
798         (pReq->sdea_service_specific_info_len ? SIZEOF_TLV_HDR + pReq->sdea_service_specific_info_len : 0);
799 
800     if ((pReq->key_info.key_type ==  NAN_SECURITY_KEY_INPUT_PMK) &&
801         (pReq->key_info.body.pmk_info.pmk_len == NAN_PMK_INFO_LEN))
802         message_len += SIZEOF_TLV_HDR + NAN_PMK_INFO_LEN;
803     else if ((pReq->key_info.key_type ==  NAN_SECURITY_KEY_INPUT_PASSPHRASE) &&
804              (pReq->key_info.body.passphrase_info.passphrase_len >=
805               NAN_SECURITY_MIN_PASSPHRASE_LEN) &&
806              (pReq->key_info.body.passphrase_info.passphrase_len <=
807               NAN_SECURITY_MAX_PASSPHRASE_LEN))
808         message_len += SIZEOF_TLV_HDR +
809                        pReq->key_info.body.passphrase_info.passphrase_len;
810 
811     pNanPublishServiceReqMsg pFwReq = (pNanPublishServiceReqMsg)malloc(message_len);
812     if (pFwReq == NULL) {
813         cleanup();
814         return WIFI_ERROR_OUT_OF_MEMORY;
815     }
816 
817     ALOGV("Message Len %zu", message_len);
818     memset(pFwReq, 0, message_len);
819     pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
820     pFwReq->fwHeader.msgId = NAN_MSG_ID_PUBLISH_SERVICE_REQ;
821     pFwReq->fwHeader.msgLen = message_len;
822     if (pReq->publish_id == 0) {
823         pFwReq->fwHeader.handle = 0xFFFF;
824     } else {
825         pFwReq->fwHeader.handle = (pReq->publish_id & 0xFF);
826     }
827     pFwReq->fwHeader.transactionId = id;
828 
829     pFwReq->publishServiceReqParams.ttl = pReq->ttl;
830     pFwReq->publishServiceReqParams.period = pReq->period;
831     pFwReq->publishServiceReqParams.replyIndFlag =
832                                    (pReq->recv_indication_cfg & BIT_3) ? 0 : 1;
833     pFwReq->publishServiceReqParams.publishType = pReq->publish_type;
834     pFwReq->publishServiceReqParams.txType = pReq->tx_type;
835 
836     pFwReq->publishServiceReqParams.rssiThresholdFlag = pReq->rssi_threshold_flag;
837     pFwReq->publishServiceReqParams.matchAlg = pReq->publish_match_indicator;
838     pFwReq->publishServiceReqParams.count = pReq->publish_count;
839     pFwReq->publishServiceReqParams.connmap = pReq->connmap;
840     pFwReq->publishServiceReqParams.pubTerminatedIndDisableFlag =
841                                    (pReq->recv_indication_cfg & BIT_0) ? 1 : 0;
842     pFwReq->publishServiceReqParams.pubMatchExpiredIndDisableFlag =
843                                    (pReq->recv_indication_cfg & BIT_1) ? 1 : 0;
844     pFwReq->publishServiceReqParams.followupRxIndDisableFlag =
845                                    (pReq->recv_indication_cfg & BIT_2) ? 1 : 0;
846 
847     pFwReq->publishServiceReqParams.reserved2 = 0;
848 
849     u8* tlvs = pFwReq->ptlv;
850     if (pReq->service_name_len) {
851         tlvs = addTlv(NAN_TLV_TYPE_SERVICE_NAME, pReq->service_name_len,
852                       (const u8*)&pReq->service_name[0], tlvs);
853     }
854     if (pReq->service_specific_info_len) {
855         tlvs = addTlv(NAN_TLV_TYPE_SERVICE_SPECIFIC_INFO, pReq->service_specific_info_len,
856                       (const u8*)&pReq->service_specific_info[0], tlvs);
857     }
858     if (pReq->rx_match_filter_len) {
859         tlvs = addTlv(NAN_TLV_TYPE_RX_MATCH_FILTER, pReq->rx_match_filter_len,
860                       (const u8*)&pReq->rx_match_filter[0], tlvs);
861     }
862     if (pReq->tx_match_filter_len) {
863         tlvs = addTlv(NAN_TLV_TYPE_TX_MATCH_FILTER, pReq->tx_match_filter_len,
864                       (const u8*)&pReq->tx_match_filter[0], tlvs);
865     }
866 
867     /* Pass the Accept policy always */
868     tlvs = addTlv(NAN_TLV_TYPE_NAN_SERVICE_ACCEPT_POLICY, sizeof(NanServiceAcceptPolicy),
869                   (const u8*)&pReq->service_responder_policy, tlvs);
870 
871     if (pReq->cipher_type) {
872         NanCsidType pNanCsidType;
873         pNanCsidType.csid_type = pReq->cipher_type;
874         tlvs = addTlv(NAN_TLV_TYPE_NAN_CSID, sizeof(NanCsidType),
875                         (const u8*)&pNanCsidType, tlvs);
876     }
877 
878     if ((pReq->key_info.key_type ==  NAN_SECURITY_KEY_INPUT_PMK) &&
879         (pReq->key_info.body.pmk_info.pmk_len == NAN_PMK_INFO_LEN)) {
880         tlvs = addTlv(NAN_TLV_TYPE_NAN_PMK,
881                       pReq->key_info.body.pmk_info.pmk_len,
882                       (const u8*)&pReq->key_info.body.pmk_info.pmk[0], tlvs);
883     } else if ((pReq->key_info.key_type == NAN_SECURITY_KEY_INPUT_PASSPHRASE) &&
884         (pReq->key_info.body.passphrase_info.passphrase_len >=
885          NAN_SECURITY_MIN_PASSPHRASE_LEN) &&
886         (pReq->key_info.body.passphrase_info.passphrase_len <=
887          NAN_SECURITY_MAX_PASSPHRASE_LEN)) {
888         tlvs = addTlv(NAN_TLV_TYPE_NAN_PASSPHRASE,
889                   pReq->key_info.body.passphrase_info.passphrase_len,
890                   (const u8*)&pReq->key_info.body.passphrase_info.passphrase[0],
891                   tlvs);
892     }
893 
894     if (pReq->sdea_params.config_nan_data_path ||
895         pReq->sdea_params.security_cfg ||
896         pReq->sdea_params.ranging_state ||
897         pReq->sdea_params.range_report ||
898         pReq->sdea_params.qos_cfg) {
899         NanFWSdeaCtrlParams pNanFWSdeaCtrlParams;
900         memset(&pNanFWSdeaCtrlParams, 0, sizeof(NanFWSdeaCtrlParams));
901 
902         if (pReq->sdea_params.config_nan_data_path) {
903             pNanFWSdeaCtrlParams.data_path_required = 1;
904             pNanFWSdeaCtrlParams.data_path_type =
905                                   (pReq->sdea_params.ndp_type & BIT_0) ?
906                                   NAN_DATA_PATH_MULTICAST_MSG :
907                                   NAN_DATA_PATH_UNICAST_MSG;
908 
909         }
910         if (pReq->sdea_params.security_cfg) {
911             pNanFWSdeaCtrlParams.security_required =
912                                          pReq->sdea_params.security_cfg;
913         }
914         if (pReq->sdea_params.ranging_state) {
915             pNanFWSdeaCtrlParams.ranging_required =
916                                          pReq->sdea_params.ranging_state;
917         }
918         if (pReq->sdea_params.range_report) {
919             pNanFWSdeaCtrlParams.range_report =
920                 (((pReq->sdea_params.range_report & NAN_ENABLE_RANGE_REPORT) >> 1) ? 1 : 0);
921         }
922         if (pReq->sdea_params.qos_cfg) {
923             pNanFWSdeaCtrlParams.qos_required = pReq->sdea_params.qos_cfg;
924         }
925         tlvs = addTlv(NAN_TLV_TYPE_SDEA_CTRL_PARAMS, sizeof(NanFWSdeaCtrlParams),
926                         (const u8*)&pNanFWSdeaCtrlParams, tlvs);
927     }
928 
929     if (pReq->ranging_cfg.ranging_interval_msec ||
930         pReq->ranging_cfg.config_ranging_indications ||
931         pReq->ranging_cfg.distance_ingress_mm ||
932         pReq->ranging_cfg.distance_egress_mm) {
933         NanFWRangeConfigParams pNanFWRangingCfg;
934 
935         memset(&pNanFWRangingCfg, 0, sizeof(NanFWRangeConfigParams));
936         pNanFWRangingCfg.range_interval =
937                                 pReq->ranging_cfg.ranging_interval_msec;
938         pNanFWRangingCfg.ranging_indication_event =
939             ((pReq->ranging_cfg.config_ranging_indications & NAN_RANGING_INDICATE_CONTINUOUS_MASK) |
940             (pReq->ranging_cfg.config_ranging_indications & NAN_RANGING_INDICATE_INGRESS_MET_MASK) |
941             (pReq->ranging_cfg.config_ranging_indications & NAN_RANGING_INDICATE_EGRESS_MET_MASK));
942 
943         pNanFWRangingCfg.ranging_indication_event = pReq->ranging_cfg.config_ranging_indications;
944         if (pReq->ranging_cfg.config_ranging_indications & NAN_RANGING_INDICATE_INGRESS_MET_MASK)
945             pNanFWRangingCfg.geo_fence_threshold.inner_threshold =
946                                         pReq->ranging_cfg.distance_ingress_mm;
947         if (pReq->ranging_cfg.config_ranging_indications & NAN_RANGING_INDICATE_EGRESS_MET_MASK)
948             pNanFWRangingCfg.geo_fence_threshold.outer_threshold =
949                                        pReq->ranging_cfg.distance_egress_mm;
950         tlvs = addTlv(NAN_TLV_TYPE_NAN_RANGING_CFG, sizeof(NanFWRangeConfigParams),
951                                                     (const u8*)&pNanFWRangingCfg, tlvs);
952     }
953 
954     if (pReq->sdea_service_specific_info_len) {
955         tlvs = addTlv(NAN_TLV_TYPE_SDEA_SERVICE_SPECIFIC_INFO, pReq->sdea_service_specific_info_len,
956                       (const u8*)&pReq->sdea_service_specific_info[0], tlvs);
957     }
958 
959     if (pReq->range_response_cfg.publish_id || pReq->range_response_cfg.ranging_response) {
960 
961         NanFWRangeReqMsg pNanFWRangeReqMsg;
962         memset(&pNanFWRangeReqMsg, 0, sizeof(NanFWRangeReqMsg));
963         pNanFWRangeReqMsg.range_id =
964                                 (u16)pReq->range_response_cfg.publish_id;
965         CHAR_ARRAY_TO_MAC_ADDR(pReq->range_response_cfg.peer_addr, pNanFWRangeReqMsg.range_mac_addr);
966         pNanFWRangeReqMsg.ranging_accept =
967             ((pReq->range_response_cfg.ranging_response == NAN_RANGE_REQUEST_ACCEPT) ? 1 : 0);
968         pNanFWRangeReqMsg.ranging_reject =
969             ((pReq->range_response_cfg.ranging_response == NAN_RANGE_REQUEST_REJECT) ? 1 : 0);
970         pNanFWRangeReqMsg.ranging_cancel =
971             ((pReq->range_response_cfg.ranging_response == NAN_RANGE_REQUEST_CANCEL) ? 1 : 0);
972         tlvs = addTlv(NAN_TLV_TYPE_NAN20_RANGING_REQUEST, sizeof(NanFWRangeReqMsg),
973                                                     (const u8*)&pNanFWRangeReqMsg, tlvs);
974     }
975 
976     mVendorData = (char *)pFwReq;
977     mDataLen = message_len;
978 
979     ret = WIFI_SUCCESS;
980     if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
981         ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
982         if (ret != WIFI_SUCCESS) {
983             ALOGE("%s: put_bytes Error:%d",__func__, ret);
984             cleanup();
985             return ret;
986         }
987     } else {
988         struct nlattr *nl_data;
989 
990         nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
991         if (!nl_data) {
992             cleanup();
993             return WIFI_ERROR_INVALID_ARGS;
994         }
995         if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
996                              mVendorData, mDataLen)) {
997             ALOGE("%s: put attr error", __func__);
998             cleanup();
999             return WIFI_ERROR_INVALID_ARGS;
1000         }
1001         attr_end(nl_data);
1002     }
1003     hexdump(mVendorData, mDataLen);
1004     return ret;
1005 }
1006 
putNanPublishCancel(transaction_id id,const NanPublishCancelRequest * pReq)1007 wifi_error NanCommand::putNanPublishCancel(transaction_id id, const NanPublishCancelRequest *pReq)
1008 {
1009     wifi_error ret;
1010     ALOGV("NAN_PUBLISH_CANCEL");
1011     if (pReq == NULL) {
1012         cleanup();
1013         return WIFI_ERROR_INVALID_ARGS;
1014     }
1015     size_t message_len = sizeof(NanPublishServiceCancelReqMsg);
1016 
1017     pNanPublishServiceCancelReqMsg pFwReq =
1018         (pNanPublishServiceCancelReqMsg)malloc(message_len);
1019     if (pFwReq == NULL) {
1020         cleanup();
1021         return WIFI_ERROR_OUT_OF_MEMORY;
1022     }
1023 
1024     ALOGV("Message Len %zu", message_len);
1025     memset(pFwReq, 0, message_len);
1026     pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
1027     pFwReq->fwHeader.msgId = NAN_MSG_ID_PUBLISH_SERVICE_CANCEL_REQ;
1028     pFwReq->fwHeader.msgLen = message_len;
1029     pFwReq->fwHeader.handle = (pReq->publish_id & 0xFF);
1030     pFwReq->fwHeader.transactionId = id;
1031 
1032     mVendorData = (char *)pFwReq;
1033     mDataLen = message_len;
1034 
1035     ret = WIFI_SUCCESS;
1036     if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
1037         ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
1038         if (ret != WIFI_SUCCESS) {
1039             ALOGE("%s: put_bytes Error:%d",__func__, ret);
1040             cleanup();
1041             return ret;
1042         }
1043     } else {
1044         struct nlattr *nl_data;
1045 
1046         nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
1047         if (!nl_data) {
1048             cleanup();
1049             return WIFI_ERROR_INVALID_ARGS;
1050         }
1051 
1052         if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
1053                              mVendorData, mDataLen)) {
1054             ALOGE("%s: put attr error", __func__);
1055             cleanup();
1056             return WIFI_ERROR_INVALID_ARGS;
1057         }
1058         attr_end(nl_data);
1059     }
1060     hexdump(mVendorData, mDataLen);
1061     return ret;
1062 }
1063 
putNanSubscribe(transaction_id id,const NanSubscribeRequest * pReq)1064 wifi_error NanCommand::putNanSubscribe(transaction_id id,
1065                                 const NanSubscribeRequest *pReq)
1066 {
1067     wifi_error ret;
1068 
1069     ALOGV("NAN_SUBSCRIBE");
1070     if (pReq == NULL) {
1071         cleanup();
1072         return WIFI_ERROR_INVALID_ARGS;
1073     }
1074 
1075     size_t message_len =
1076         sizeof(NanMsgHeader) + sizeof(NanSubscribeServiceReqParams) +
1077         (pReq->service_name_len ? SIZEOF_TLV_HDR + pReq->service_name_len : 0) +
1078         (pReq->service_specific_info_len ? SIZEOF_TLV_HDR + pReq->service_specific_info_len : 0) +
1079         (pReq->rx_match_filter_len ? SIZEOF_TLV_HDR + pReq->rx_match_filter_len : 0) +
1080         (pReq->tx_match_filter_len ? SIZEOF_TLV_HDR + pReq->tx_match_filter_len : 0) +
1081         (pReq->cipher_type ? SIZEOF_TLV_HDR + sizeof(NanCsidType) : 0) +
1082         ((pReq->sdea_params.config_nan_data_path || pReq->sdea_params.security_cfg ||
1083           pReq->sdea_params.ranging_state || pReq->sdea_params.range_report ||
1084           pReq->sdea_params.qos_cfg) ?
1085           SIZEOF_TLV_HDR + sizeof(NanFWSdeaCtrlParams) : 0) +
1086         ((pReq->ranging_cfg.ranging_interval_msec || pReq->ranging_cfg.config_ranging_indications ||
1087           pReq->ranging_cfg.distance_ingress_mm || pReq->ranging_cfg.distance_egress_mm) ?
1088           SIZEOF_TLV_HDR + sizeof(NanFWRangeConfigParams) : 0) +
1089         ((pReq->range_response_cfg.requestor_instance_id ||
1090           pReq->range_response_cfg.ranging_response) ?
1091           SIZEOF_TLV_HDR + sizeof(NanFWRangeReqMsg) : 0) +
1092         (pReq->sdea_service_specific_info_len ? SIZEOF_TLV_HDR + pReq->sdea_service_specific_info_len : 0);
1093 
1094     message_len += \
1095         (pReq->num_intf_addr_present * (SIZEOF_TLV_HDR + NAN_MAC_ADDR_LEN));
1096 
1097 
1098     if ((pReq->key_info.key_type ==  NAN_SECURITY_KEY_INPUT_PMK) &&
1099         (pReq->key_info.body.pmk_info.pmk_len == NAN_PMK_INFO_LEN))
1100         message_len += SIZEOF_TLV_HDR + NAN_PMK_INFO_LEN;
1101     else if ((pReq->key_info.key_type ==  NAN_SECURITY_KEY_INPUT_PASSPHRASE) &&
1102              (pReq->key_info.body.passphrase_info.passphrase_len >=
1103               NAN_SECURITY_MIN_PASSPHRASE_LEN) &&
1104              (pReq->key_info.body.passphrase_info.passphrase_len <=
1105               NAN_SECURITY_MAX_PASSPHRASE_LEN))
1106         message_len += SIZEOF_TLV_HDR +
1107                        pReq->key_info.body.passphrase_info.passphrase_len;
1108 
1109 
1110     pNanSubscribeServiceReqMsg pFwReq = (pNanSubscribeServiceReqMsg)malloc(message_len);
1111     if (pFwReq == NULL) {
1112         cleanup();
1113         return WIFI_ERROR_OUT_OF_MEMORY;
1114     }
1115 
1116     ALOGV("Message Len %zu", message_len);
1117     memset(pFwReq, 0, message_len);
1118     pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
1119     pFwReq->fwHeader.msgId = NAN_MSG_ID_SUBSCRIBE_SERVICE_REQ;
1120     pFwReq->fwHeader.msgLen = message_len;
1121     if (pReq->subscribe_id == 0) {
1122         pFwReq->fwHeader.handle = 0xFFFF;
1123     } else {
1124         pFwReq->fwHeader.handle = (pReq->subscribe_id & 0xFF);
1125     }
1126     pFwReq->fwHeader.transactionId = id;
1127 
1128     pFwReq->subscribeServiceReqParams.ttl = pReq->ttl;
1129     pFwReq->subscribeServiceReqParams.period = pReq->period;
1130     pFwReq->subscribeServiceReqParams.subscribeType = pReq->subscribe_type;
1131     pFwReq->subscribeServiceReqParams.srfAttr = pReq->serviceResponseFilter;
1132     pFwReq->subscribeServiceReqParams.srfInclude = pReq->serviceResponseInclude;
1133     pFwReq->subscribeServiceReqParams.srfSend = pReq->useServiceResponseFilter;
1134     pFwReq->subscribeServiceReqParams.ssiRequired = pReq->ssiRequiredForMatchIndication;
1135     pFwReq->subscribeServiceReqParams.matchAlg = pReq->subscribe_match_indicator;
1136     pFwReq->subscribeServiceReqParams.count = pReq->subscribe_count;
1137     pFwReq->subscribeServiceReqParams.rssiThresholdFlag = pReq->rssi_threshold_flag;
1138     pFwReq->subscribeServiceReqParams.subTerminatedIndDisableFlag =
1139                                    (pReq->recv_indication_cfg & BIT_0) ? 1 : 0;
1140     pFwReq->subscribeServiceReqParams.subMatchExpiredIndDisableFlag =
1141                                    (pReq->recv_indication_cfg & BIT_1) ? 1 : 0;
1142     pFwReq->subscribeServiceReqParams.followupRxIndDisableFlag =
1143                                    (pReq->recv_indication_cfg & BIT_2) ? 1 : 0;
1144     pFwReq->subscribeServiceReqParams.connmap = pReq->connmap;
1145     pFwReq->subscribeServiceReqParams.reserved = 0;
1146 
1147     u8* tlvs = pFwReq->ptlv;
1148     if (pReq->service_name_len) {
1149         tlvs = addTlv(NAN_TLV_TYPE_SERVICE_NAME, pReq->service_name_len,
1150                       (const u8*)&pReq->service_name[0], tlvs);
1151     }
1152     if (pReq->service_specific_info_len) {
1153         tlvs = addTlv(NAN_TLV_TYPE_SERVICE_SPECIFIC_INFO, pReq->service_specific_info_len,
1154                       (const u8*)&pReq->service_specific_info[0], tlvs);
1155     }
1156     if (pReq->rx_match_filter_len) {
1157         tlvs = addTlv(NAN_TLV_TYPE_RX_MATCH_FILTER, pReq->rx_match_filter_len,
1158                       (const u8*)&pReq->rx_match_filter[0], tlvs);
1159     }
1160     if (pReq->tx_match_filter_len) {
1161         tlvs = addTlv(NAN_TLV_TYPE_TX_MATCH_FILTER, pReq->tx_match_filter_len,
1162                       (const u8*)&pReq->tx_match_filter[0], tlvs);
1163     }
1164 
1165     int i = 0;
1166     for (i = 0; i < pReq->num_intf_addr_present; i++)
1167     {
1168         tlvs = addTlv(NAN_TLV_TYPE_MAC_ADDRESS,
1169                       NAN_MAC_ADDR_LEN,
1170                       (const u8*)&pReq->intf_addr[i][0], tlvs);
1171     }
1172 
1173     if (pReq->cipher_type) {
1174         NanCsidType pNanCsidType;
1175         pNanCsidType.csid_type = pReq->cipher_type;
1176         tlvs = addTlv(NAN_TLV_TYPE_NAN_CSID, sizeof(NanCsidType),
1177                         (const u8*)&pNanCsidType, tlvs);
1178     }
1179 
1180     if ((pReq->key_info.key_type ==  NAN_SECURITY_KEY_INPUT_PMK) &&
1181         (pReq->key_info.body.pmk_info.pmk_len == NAN_PMK_INFO_LEN)) {
1182         tlvs = addTlv(NAN_TLV_TYPE_NAN_PMK,
1183                       pReq->key_info.body.pmk_info.pmk_len,
1184                       (const u8*)&pReq->key_info.body.pmk_info.pmk[0], tlvs);
1185     } else if ((pReq->key_info.key_type == NAN_SECURITY_KEY_INPUT_PASSPHRASE) &&
1186         (pReq->key_info.body.passphrase_info.passphrase_len >=
1187          NAN_SECURITY_MIN_PASSPHRASE_LEN) &&
1188         (pReq->key_info.body.passphrase_info.passphrase_len <=
1189          NAN_SECURITY_MAX_PASSPHRASE_LEN)) {
1190         tlvs = addTlv(NAN_TLV_TYPE_NAN_PASSPHRASE,
1191                   pReq->key_info.body.passphrase_info.passphrase_len,
1192                   (const u8*)&pReq->key_info.body.passphrase_info.passphrase[0],
1193                   tlvs);
1194     }
1195 
1196     if (pReq->sdea_params.config_nan_data_path ||
1197         pReq->sdea_params.security_cfg ||
1198         pReq->sdea_params.ranging_state ||
1199         pReq->sdea_params.range_report ||
1200         pReq->sdea_params.qos_cfg) {
1201         NanFWSdeaCtrlParams pNanFWSdeaCtrlParams;
1202         memset(&pNanFWSdeaCtrlParams, 0, sizeof(NanFWSdeaCtrlParams));
1203 
1204         if (pReq->sdea_params.config_nan_data_path) {
1205             pNanFWSdeaCtrlParams.data_path_required = 1;
1206             pNanFWSdeaCtrlParams.data_path_type =
1207                                   (pReq->sdea_params.ndp_type & BIT_0) ?
1208                                   NAN_DATA_PATH_MULTICAST_MSG :
1209                                   NAN_DATA_PATH_UNICAST_MSG;
1210 
1211         }
1212         if (pReq->sdea_params.security_cfg) {
1213             pNanFWSdeaCtrlParams.security_required =
1214                                          pReq->sdea_params.security_cfg;
1215         }
1216         if (pReq->sdea_params.ranging_state) {
1217             pNanFWSdeaCtrlParams.ranging_required =
1218                                          pReq->sdea_params.ranging_state;
1219         }
1220         if (pReq->sdea_params.range_report) {
1221             pNanFWSdeaCtrlParams.range_report =
1222                 ((pReq->sdea_params.range_report & NAN_ENABLE_RANGE_REPORT >> 1) ? 1 : 0);
1223         }
1224         if (pReq->sdea_params.qos_cfg) {
1225             pNanFWSdeaCtrlParams.qos_required = pReq->sdea_params.qos_cfg;
1226         }
1227         tlvs = addTlv(NAN_TLV_TYPE_SDEA_CTRL_PARAMS, sizeof(NanFWSdeaCtrlParams),
1228                         (const u8*)&pNanFWSdeaCtrlParams, tlvs);
1229 
1230     }
1231 
1232     if (pReq->ranging_cfg.ranging_interval_msec || pReq->ranging_cfg.config_ranging_indications || pReq->ranging_cfg.distance_ingress_mm
1233         || pReq->ranging_cfg.distance_egress_mm) {
1234         NanFWRangeConfigParams pNanFWRangingCfg;
1235         memset(&pNanFWRangingCfg, 0, sizeof(NanFWRangeConfigParams));
1236         pNanFWRangingCfg.range_interval =
1237                                 pReq->ranging_cfg.ranging_interval_msec;
1238         pNanFWRangingCfg.ranging_indication_event =
1239             ((pReq->ranging_cfg.config_ranging_indications & NAN_RANGING_INDICATE_CONTINUOUS_MASK) |
1240             (pReq->ranging_cfg.config_ranging_indications & NAN_RANGING_INDICATE_INGRESS_MET_MASK) |
1241             (pReq->ranging_cfg.config_ranging_indications & NAN_RANGING_INDICATE_EGRESS_MET_MASK));
1242 
1243         pNanFWRangingCfg.ranging_indication_event =
1244                                           pReq->ranging_cfg.config_ranging_indications;
1245         if (pReq->ranging_cfg.config_ranging_indications & NAN_RANGING_INDICATE_INGRESS_MET_MASK)
1246             pNanFWRangingCfg.geo_fence_threshold.inner_threshold =
1247                                         pReq->ranging_cfg.distance_ingress_mm;
1248         if (pReq->ranging_cfg.config_ranging_indications & NAN_RANGING_INDICATE_EGRESS_MET_MASK)
1249             pNanFWRangingCfg.geo_fence_threshold.outer_threshold =
1250                                        pReq->ranging_cfg.distance_egress_mm;
1251         tlvs = addTlv(NAN_TLV_TYPE_NAN_RANGING_CFG, sizeof(NanFWRangeConfigParams),
1252                                                     (const u8*)&pNanFWRangingCfg, tlvs);
1253     }
1254 
1255     if (pReq->sdea_service_specific_info_len) {
1256         tlvs = addTlv(NAN_TLV_TYPE_SDEA_SERVICE_SPECIFIC_INFO, pReq->sdea_service_specific_info_len,
1257                       (const u8*)&pReq->sdea_service_specific_info[0], tlvs);
1258     }
1259 
1260     if (pReq->range_response_cfg.requestor_instance_id || pReq->range_response_cfg.ranging_response) {
1261         NanFWRangeReqMsg pNanFWRangeReqMsg;
1262         memset(&pNanFWRangeReqMsg, 0, sizeof(NanFWRangeReqMsg));
1263         pNanFWRangeReqMsg.range_id =
1264                                 pReq->range_response_cfg.requestor_instance_id;
1265         memcpy(&pNanFWRangeReqMsg.range_mac_addr, &pReq->range_response_cfg.peer_addr, NAN_MAC_ADDR_LEN);
1266         pNanFWRangeReqMsg.ranging_accept =
1267             ((pReq->range_response_cfg.ranging_response == NAN_RANGE_REQUEST_ACCEPT) ? 1 : 0);
1268         pNanFWRangeReqMsg.ranging_reject =
1269             ((pReq->range_response_cfg.ranging_response == NAN_RANGE_REQUEST_REJECT) ? 1 : 0);
1270         pNanFWRangeReqMsg.ranging_cancel =
1271             ((pReq->range_response_cfg.ranging_response == NAN_RANGE_REQUEST_CANCEL) ? 1 : 0);
1272         tlvs = addTlv(NAN_TLV_TYPE_NAN20_RANGING_REQUEST, sizeof(NanFWRangeReqMsg),
1273                                                     (const u8*)&pNanFWRangeReqMsg, tlvs);
1274     }
1275 
1276     mVendorData = (char *)pFwReq;
1277     mDataLen = message_len;
1278     ret = WIFI_SUCCESS;
1279     if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
1280         ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
1281         if (ret != WIFI_SUCCESS) {
1282             ALOGE("%s: put_bytes Error:%d",__func__, ret);
1283             cleanup();
1284             return ret;
1285         }
1286     } else {
1287         struct nlattr *nl_data;
1288 
1289         nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
1290         if (!nl_data) {
1291             cleanup();
1292             return WIFI_ERROR_INVALID_ARGS;
1293         }
1294 
1295         if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
1296                              mVendorData, mDataLen)) {
1297             ALOGE("%s: put attr error", __func__);
1298             cleanup();
1299             return WIFI_ERROR_INVALID_ARGS;
1300         }
1301         attr_end(nl_data);
1302     }
1303     hexdump(mVendorData, mDataLen);
1304     return ret;
1305 }
1306 
putNanSubscribeCancel(transaction_id id,const NanSubscribeCancelRequest * pReq)1307 wifi_error NanCommand::putNanSubscribeCancel(transaction_id id,
1308                                       const NanSubscribeCancelRequest *pReq)
1309 {
1310     wifi_error ret;
1311     ALOGV("NAN_SUBSCRIBE_CANCEL");
1312     if (pReq == NULL) {
1313         cleanup();
1314         return WIFI_ERROR_INVALID_ARGS;
1315     }
1316     size_t message_len = sizeof(NanSubscribeServiceCancelReqMsg);
1317 
1318     pNanSubscribeServiceCancelReqMsg pFwReq =
1319         (pNanSubscribeServiceCancelReqMsg)malloc(message_len);
1320     if (pFwReq == NULL) {
1321         cleanup();
1322         return WIFI_ERROR_OUT_OF_MEMORY;
1323     }
1324 
1325     ALOGV("Message Len %zu", message_len);
1326     memset(pFwReq, 0, message_len);
1327     pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
1328     pFwReq->fwHeader.msgId = NAN_MSG_ID_SUBSCRIBE_SERVICE_CANCEL_REQ;
1329     pFwReq->fwHeader.msgLen = message_len;
1330     pFwReq->fwHeader.handle = (pReq->subscribe_id & 0xFF);
1331     pFwReq->fwHeader.transactionId = id;
1332 
1333     mVendorData = (char *)pFwReq;
1334     mDataLen = message_len;
1335     ret = WIFI_SUCCESS;
1336     if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
1337         ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
1338         if (ret != WIFI_SUCCESS) {
1339             ALOGE("%s: put_bytes Error:%d",__func__, ret);
1340             cleanup();
1341             return ret;
1342         }
1343     } else {
1344         struct nlattr *nl_data;
1345 
1346         nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
1347         if (!nl_data) {
1348             cleanup();
1349             return WIFI_ERROR_INVALID_ARGS;
1350         }
1351 
1352         if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
1353                              mVendorData, mDataLen)) {
1354             ALOGE("%s: put attr error", __func__);
1355             cleanup();
1356             return WIFI_ERROR_INVALID_ARGS;
1357         }
1358         attr_end(nl_data);
1359     }
1360     hexdump(mVendorData, mDataLen);
1361     return ret;
1362 }
1363 
putNanTransmitFollowup(transaction_id id,const NanTransmitFollowupRequest * pReq)1364 wifi_error NanCommand::putNanTransmitFollowup(transaction_id id,
1365                                        const NanTransmitFollowupRequest *pReq)
1366 {
1367     wifi_error ret;
1368     ALOGV("TRANSMIT_FOLLOWUP");
1369     if (pReq == NULL) {
1370         cleanup();
1371         return WIFI_ERROR_INVALID_ARGS;
1372     }
1373 
1374     size_t message_len =
1375         sizeof(NanMsgHeader) + sizeof(NanTransmitFollowupReqParams) +
1376         (pReq->service_specific_info_len ? SIZEOF_TLV_HDR +
1377          pReq->service_specific_info_len : 0) +
1378         (pReq->sdea_service_specific_info_len ? SIZEOF_TLV_HDR + pReq->sdea_service_specific_info_len : 0);
1379 
1380     /* Mac address needs to be added in TLV */
1381     message_len += (SIZEOF_TLV_HDR + sizeof(pReq->addr));
1382 
1383     pNanTransmitFollowupReqMsg pFwReq = (pNanTransmitFollowupReqMsg)malloc(message_len);
1384     if (pFwReq == NULL) {
1385         cleanup();
1386         return WIFI_ERROR_OUT_OF_MEMORY;
1387     }
1388 
1389     ALOGV("Message Len %zu", message_len);
1390     memset (pFwReq, 0, message_len);
1391     pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
1392     pFwReq->fwHeader.msgId = NAN_MSG_ID_TRANSMIT_FOLLOWUP_REQ;
1393     pFwReq->fwHeader.msgLen = message_len;
1394     pFwReq->fwHeader.handle = (pReq->publish_subscribe_id & 0xFF);
1395     pFwReq->fwHeader.transactionId = id;
1396 
1397     pFwReq->transmitFollowupReqParams.matchHandle = pReq->requestor_instance_id;
1398     if (pReq->priority != NAN_TX_PRIORITY_HIGH) {
1399         pFwReq->transmitFollowupReqParams.priority = 1;
1400     } else {
1401         pFwReq->transmitFollowupReqParams.priority = 2;
1402     }
1403     pFwReq->transmitFollowupReqParams.window = pReq->dw_or_faw;
1404     pFwReq->transmitFollowupReqParams.followupTxRspDisableFlag =
1405                                    (pReq->recv_indication_cfg & BIT_0) ? 1 : 0;
1406     pFwReq->transmitFollowupReqParams.reserved = 0;
1407 
1408     u8* tlvs = pFwReq->ptlv;
1409 
1410     /* Mac address needs to be added in TLV */
1411     tlvs = addTlv(NAN_TLV_TYPE_MAC_ADDRESS, sizeof(pReq->addr),
1412                   (const u8*)&pReq->addr[0], tlvs);
1413     u16 tlv_type = NAN_TLV_TYPE_SERVICE_SPECIFIC_INFO;
1414 
1415     if (pReq->service_specific_info_len) {
1416         tlvs = addTlv(tlv_type, pReq->service_specific_info_len,
1417                       (const u8*)&pReq->service_specific_info[0], tlvs);
1418     }
1419 
1420     if (pReq->sdea_service_specific_info_len) {
1421         tlvs = addTlv(NAN_TLV_TYPE_SDEA_SERVICE_SPECIFIC_INFO, pReq->sdea_service_specific_info_len,
1422                       (const u8*)&pReq->sdea_service_specific_info[0], tlvs);
1423     }
1424 
1425     mVendorData = (char *)pFwReq;
1426     mDataLen = message_len;
1427 
1428     ret = WIFI_SUCCESS;
1429     if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
1430         ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
1431         if (ret != WIFI_SUCCESS) {
1432             ALOGE("%s: put_bytes Error:%d",__func__, ret);
1433             cleanup();
1434             return ret;
1435         }
1436     } else {
1437         struct nlattr *nl_data;
1438 
1439         nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
1440         if (!nl_data) {
1441             cleanup();
1442             return WIFI_ERROR_INVALID_ARGS;
1443         }
1444 
1445         if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
1446                              mVendorData, mDataLen)) {
1447             ALOGE("%s: put attr error", __func__);
1448             cleanup();
1449             return WIFI_ERROR_INVALID_ARGS;
1450         }
1451         attr_end(nl_data);
1452     }
1453     hexdump(mVendorData, mDataLen);
1454     return ret;
1455 }
1456 
putNanStats(transaction_id id,const NanStatsRequest * pReq)1457 wifi_error NanCommand::putNanStats(transaction_id id, const NanStatsRequest *pReq)
1458 {
1459     wifi_error ret;
1460     ALOGV("NAN_STATS");
1461     if (pReq == NULL) {
1462         cleanup();
1463         return WIFI_ERROR_INVALID_ARGS;
1464     }
1465     size_t message_len = sizeof(NanStatsReqMsg);
1466 
1467     pNanStatsReqMsg pFwReq =
1468         (pNanStatsReqMsg)malloc(message_len);
1469     if (pFwReq == NULL) {
1470         cleanup();
1471         return WIFI_ERROR_OUT_OF_MEMORY;
1472     }
1473 
1474     ALOGV("Message Len %zu", message_len);
1475     memset(pFwReq, 0, message_len);
1476     pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
1477     pFwReq->fwHeader.msgId = NAN_MSG_ID_STATS_REQ;
1478     pFwReq->fwHeader.msgLen = message_len;
1479     pFwReq->fwHeader.transactionId = id;
1480 
1481     pFwReq->statsReqParams.statsType = pReq->stats_type;
1482     pFwReq->statsReqParams.clear = pReq->clear;
1483     pFwReq->statsReqParams.reserved = 0;
1484 
1485     mVendorData = (char *)pFwReq;
1486     mDataLen = message_len;
1487 
1488     ret = WIFI_SUCCESS;
1489     if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
1490         ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
1491         if (ret != WIFI_SUCCESS) {
1492             ALOGE("%s: put_bytes Error:%d",__func__, ret);
1493             cleanup();
1494             return ret;
1495         }
1496     } else {
1497         struct nlattr *nl_data;
1498 
1499         nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
1500         if (!nl_data) {
1501             cleanup();
1502             return WIFI_ERROR_INVALID_ARGS;
1503         }
1504 
1505         if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
1506                              mVendorData, mDataLen)) {
1507             ALOGE("%s: put attr error", __func__);
1508             cleanup();
1509             return WIFI_ERROR_INVALID_ARGS;
1510         }
1511         attr_end(nl_data);
1512     }
1513     hexdump(mVendorData, mDataLen);
1514     return ret;
1515 }
1516 
putNanTCA(transaction_id id,const NanTCARequest * pReq)1517 wifi_error NanCommand::putNanTCA(transaction_id id, const NanTCARequest *pReq)
1518 {
1519     wifi_error ret;
1520     ALOGV("NAN_TCA");
1521     if (pReq == NULL) {
1522         cleanup();
1523         return WIFI_ERROR_INVALID_ARGS;
1524     }
1525     size_t message_len = sizeof(NanTcaReqMsg);
1526 
1527     message_len += (SIZEOF_TLV_HDR + 2 * sizeof(u32));
1528     pNanTcaReqMsg pFwReq =
1529         (pNanTcaReqMsg)malloc(message_len);
1530     if (pFwReq == NULL) {
1531         cleanup();
1532         return WIFI_ERROR_OUT_OF_MEMORY;
1533     }
1534 
1535     ALOGV("Message Len %zu", message_len);
1536     memset(pFwReq, 0, message_len);
1537     pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
1538     pFwReq->fwHeader.msgId = NAN_MSG_ID_TCA_REQ;
1539     pFwReq->fwHeader.msgLen = message_len;
1540     pFwReq->fwHeader.transactionId = id;
1541 
1542     u32 tcaReqParams[2];
1543     memset (tcaReqParams, 0, sizeof(tcaReqParams));
1544     tcaReqParams[0] = (pReq->rising_direction_evt_flag & 0x01);
1545     tcaReqParams[0] |= (pReq->falling_direction_evt_flag & 0x01) << 1;
1546     tcaReqParams[0] |= (pReq->clear & 0x01) << 2;
1547     tcaReqParams[1] = pReq->threshold;
1548 
1549     u8* tlvs = pFwReq->ptlv;
1550 
1551     if (pReq->tca_type == NAN_TCA_ID_CLUSTER_SIZE) {
1552         tlvs = addTlv(NAN_TLV_TYPE_CLUSTER_SIZE_REQ, sizeof(tcaReqParams),
1553                       (const u8*)&tcaReqParams[0], tlvs);
1554     } else {
1555         ALOGE("%s: Unrecognized tca_type:%u", __FUNCTION__, pReq->tca_type);
1556         cleanup();
1557         return WIFI_ERROR_INVALID_ARGS;
1558     }
1559 
1560     mVendorData = (char *)pFwReq;
1561     mDataLen = message_len;
1562 
1563     ret = WIFI_SUCCESS;
1564     if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
1565         ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
1566         if (ret != WIFI_SUCCESS) {
1567             ALOGE("%s: put_bytes Error:%d",__func__, ret);
1568             cleanup();
1569             return ret;
1570         }
1571     } else {
1572         struct nlattr *nl_data;
1573 
1574         nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
1575         if (!nl_data) {
1576             cleanup();
1577             return WIFI_ERROR_INVALID_ARGS;
1578         }
1579 
1580         if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
1581                              mVendorData, mDataLen)) {
1582             ALOGE("%s: put attr error", __func__);
1583             cleanup();
1584             return WIFI_ERROR_INVALID_ARGS;
1585         }
1586         attr_end(nl_data);
1587     }
1588     hexdump(mVendorData, mDataLen);
1589     return ret;
1590 }
1591 
putNanBeaconSdfPayload(transaction_id id,const NanBeaconSdfPayloadRequest * pReq)1592 wifi_error NanCommand::putNanBeaconSdfPayload(transaction_id id,
1593                                        const NanBeaconSdfPayloadRequest *pReq)
1594 {
1595     wifi_error ret;
1596     ALOGV("NAN_BEACON_SDF_PAYLAOD");
1597     if (pReq == NULL) {
1598         cleanup();
1599         return WIFI_ERROR_INVALID_ARGS;
1600     }
1601     size_t message_len = sizeof(NanMsgHeader) + \
1602         SIZEOF_TLV_HDR + sizeof(u32) + \
1603         pReq->vsa.vsa_len;
1604 
1605     pNanBeaconSdfPayloadReqMsg pFwReq =
1606         (pNanBeaconSdfPayloadReqMsg)malloc(message_len);
1607     if (pFwReq == NULL) {
1608         cleanup();
1609         return WIFI_ERROR_OUT_OF_MEMORY;
1610     }
1611 
1612     ALOGV("Message Len %zu", message_len);
1613     memset(pFwReq, 0, message_len);
1614     pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
1615     pFwReq->fwHeader.msgId = NAN_MSG_ID_BEACON_SDF_REQ;
1616     pFwReq->fwHeader.msgLen = message_len;
1617     pFwReq->fwHeader.transactionId = id;
1618 
1619     /* Construct First 4 bytes of NanBeaconSdfPayloadReqMsg */
1620     u32 temp = 0;
1621     temp = pReq->vsa.payload_transmit_flag & 0x01;
1622     temp |= (pReq->vsa.tx_in_discovery_beacon & 0x01) << 1;
1623     temp |= (pReq->vsa.tx_in_sync_beacon & 0x01) << 2;
1624     temp |= (pReq->vsa.tx_in_service_discovery & 0x01) << 3;
1625     temp |= (pReq->vsa.vendor_oui & 0x00FFFFFF) << 8;
1626 
1627     int tlv_len = sizeof(u32) + pReq->vsa.vsa_len;
1628     u8* tempBuf = (u8*)malloc(tlv_len);
1629     if (tempBuf == NULL) {
1630         ALOGE("%s: Malloc failed", __func__);
1631         free(pFwReq);
1632         cleanup();
1633         return WIFI_ERROR_OUT_OF_MEMORY;
1634     }
1635     memset(tempBuf, 0, tlv_len);
1636     memcpy(tempBuf, &temp, sizeof(u32));
1637     memcpy((tempBuf + sizeof(u32)), pReq->vsa.vsa, pReq->vsa.vsa_len);
1638 
1639     u8* tlvs = pFwReq->ptlv;
1640 
1641     /* Write the TLVs to the message. */
1642     tlvs = addTlv(NAN_TLV_TYPE_VENDOR_SPECIFIC_ATTRIBUTE_TRANSMIT, tlv_len,
1643                   (const u8*)tempBuf, tlvs);
1644     free(tempBuf);
1645 
1646     mVendorData = (char *)pFwReq;
1647     mDataLen = message_len;
1648 
1649     ret = WIFI_SUCCESS;
1650     if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
1651         ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
1652         if (ret != WIFI_SUCCESS) {
1653             ALOGE("%s: put_bytes Error:%d",__func__, ret);
1654             cleanup();
1655             return ret;
1656         }
1657     } else {
1658         struct nlattr *nl_data;
1659 
1660         nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
1661         if (!nl_data) {
1662             cleanup();
1663             return WIFI_ERROR_INVALID_ARGS;
1664         }
1665 
1666         if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
1667                              mVendorData, mDataLen)) {
1668             ALOGE("%s: put attr error", __func__);
1669             cleanup();
1670             return WIFI_ERROR_INVALID_ARGS;
1671         }
1672         attr_end(nl_data);
1673     }
1674     hexdump(mVendorData, mDataLen);
1675     return ret;
1676 }
1677 
1678 //callback handlers registered for nl message send
error_handler_nan(struct sockaddr_nl * nla,struct nlmsgerr * err,void * arg)1679 static int error_handler_nan(struct sockaddr_nl *nla, struct nlmsgerr *err,
1680                          void *arg)
1681 {
1682     struct sockaddr_nl * tmp;
1683     int *ret = (int *)arg;
1684     tmp = nla;
1685     *ret = err->error;
1686     ALOGE("%s: Error code:%d (%s)", __func__, *ret, strerror(-(*ret)));
1687     return NL_STOP;
1688 }
1689 
1690 //callback handlers registered for nl message send
ack_handler_nan(struct nl_msg * msg,void * arg)1691 static int ack_handler_nan(struct nl_msg *msg, void *arg)
1692 {
1693     int *ret = (int *)arg;
1694     struct nl_msg * a;
1695 
1696     ALOGE("%s: called", __func__);
1697     a = msg;
1698     *ret = 0;
1699     return NL_STOP;
1700 }
1701 
1702 //callback handlers registered for nl message send
finish_handler_nan(struct nl_msg * msg,void * arg)1703 static int finish_handler_nan(struct nl_msg *msg, void *arg)
1704 {
1705   int *ret = (int *)arg;
1706   struct nl_msg * a;
1707 
1708   ALOGE("%s: called", __func__);
1709   a = msg;
1710   *ret = 0;
1711   return NL_SKIP;
1712 }
1713 
1714 
1715 //Override base class requestEvent and implement little differently here
1716 //This will send the request message
1717 //We dont wait for any response back in case of Nan as it is asynchronous
1718 //thus no wait for condition.
requestEvent()1719 wifi_error NanCommand::requestEvent()
1720 {
1721     wifi_error res;
1722     int status;
1723     struct nl_cb * cb = NULL;
1724 
1725     cb = nl_cb_alloc(NL_CB_DEFAULT);
1726     if (!cb) {
1727         ALOGE("%s: Callback allocation failed",__func__);
1728         res = WIFI_ERROR_OUT_OF_MEMORY;
1729         goto out;
1730     }
1731 
1732     if (!mInfo->cmd_sock) {
1733         ALOGE("%s: Command socket is null",__func__);
1734         res = WIFI_ERROR_OUT_OF_MEMORY;
1735         goto out;
1736     }
1737 
1738     /* send message */
1739     ALOGV("%s:Handle:%p Socket Value:%p", __func__, mInfo, mInfo->cmd_sock);
1740     status = nl_send_auto_complete(mInfo->cmd_sock, mMsg.getMessage());
1741     if (status < 0) {
1742         res = mapKernelErrortoWifiHalError(status);
1743         goto out;
1744     }
1745 
1746     status = 1;
1747 
1748     nl_cb_err(cb, NL_CB_CUSTOM, error_handler_nan, &status);
1749     nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler_nan, &status);
1750     nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler_nan, &status);
1751 
1752     // err is populated as part of finish_handler
1753     while (status > 0)
1754         nl_recvmsgs(mInfo->cmd_sock, cb);
1755 
1756     res = mapKernelErrortoWifiHalError(status);
1757 out:
1758     nl_cb_put(cb);
1759     //free the VendorData
1760     if (mVendorData) {
1761         free(mVendorData);
1762     }
1763     mVendorData = NULL;
1764     //cleanup the mMsg
1765     mMsg.destroy();
1766     return res;
1767 }
1768 
calcNanTransmitPostDiscoverySize(const NanTransmitPostDiscovery * pPostDiscovery)1769 int NanCommand::calcNanTransmitPostDiscoverySize(
1770     const NanTransmitPostDiscovery *pPostDiscovery)
1771 {
1772     /* Fixed size of u32 for Conn Type, Device Role and R flag + Dur + Rsvd*/
1773     int ret = sizeof(u32);
1774     /* size of availability interval bit map is 4 bytes */
1775     ret += sizeof(u32);
1776     /* size of mac address is 6 bytes*/
1777     ret += (SIZEOF_TLV_HDR + NAN_MAC_ADDR_LEN);
1778     if (pPostDiscovery &&
1779         pPostDiscovery->type == NAN_CONN_WLAN_MESH) {
1780         /* size of WLAN_MESH_ID  */
1781         ret += (SIZEOF_TLV_HDR + \
1782                 pPostDiscovery->mesh_id_len);
1783     }
1784     if (pPostDiscovery &&
1785         pPostDiscovery->type == NAN_CONN_WLAN_INFRA) {
1786         /* size of Infrastructure ssid  */
1787         ret += (SIZEOF_TLV_HDR + \
1788                 pPostDiscovery->infrastructure_ssid_len);
1789     }
1790     ALOGV("%s:size:%d", __func__, ret);
1791     return ret;
1792 }
1793 
fillNanSocialChannelParamVal(const NanSocialChannelScanParams * pScanParams,u32 * pChannelParamArr)1794 void NanCommand::fillNanSocialChannelParamVal(
1795     const NanSocialChannelScanParams *pScanParams,
1796     u32* pChannelParamArr)
1797 {
1798     int i;
1799     if (pChannelParamArr) {
1800         memset(pChannelParamArr, 0,
1801                NAN_MAX_SOCIAL_CHANNELS * sizeof(u32));
1802         for (i= 0; i < NAN_MAX_SOCIAL_CHANNELS; i++) {
1803             pChannelParamArr[i] = pScanParams->scan_period[i] << 16;
1804             pChannelParamArr[i] |= pScanParams->dwell_time[i] << 8;
1805         }
1806         pChannelParamArr[NAN_CHANNEL_24G_BAND] |= 6;
1807         pChannelParamArr[NAN_CHANNEL_5G_BAND_LOW]|= 44;
1808         pChannelParamArr[NAN_CHANNEL_5G_BAND_HIGH]|= 149;
1809         ALOGV("%s: Filled SocialChannelParamVal", __func__);
1810         hexdump((char*)pChannelParamArr, NAN_MAX_SOCIAL_CHANNELS * sizeof(u32));
1811     }
1812     return;
1813 }
1814 
getNanTransmitPostConnectivityCapabilityVal(const NanTransmitPostConnectivityCapability * pCapab)1815 u32 NanCommand::getNanTransmitPostConnectivityCapabilityVal(
1816     const NanTransmitPostConnectivityCapability *pCapab)
1817 {
1818     u32 ret = 0;
1819     ret |= (pCapab->payload_transmit_flag? 1:0) << 16;
1820     ret |= (pCapab->is_mesh_supported? 1:0) << 5;
1821     ret |= (pCapab->is_ibss_supported? 1:0) << 4;
1822     ret |= (pCapab->wlan_infra_field? 1:0) << 3;
1823     ret |= (pCapab->is_tdls_supported? 1:0) << 2;
1824     ret |= (pCapab->is_wfds_supported? 1:0) << 1;
1825     ret |= (pCapab->is_wfd_supported? 1:0);
1826     ALOGV("%s: val:%d", __func__, ret);
1827     return ret;
1828 }
1829 
fillNanTransmitPostDiscoveryVal(const NanTransmitPostDiscovery * pTxDisc,u8 * pOutValue)1830 void NanCommand::fillNanTransmitPostDiscoveryVal(
1831     const NanTransmitPostDiscovery *pTxDisc,
1832     u8 *pOutValue)
1833 {
1834 
1835     if (pTxDisc && pOutValue) {
1836         u8 *tlvs = &pOutValue[8];
1837         pOutValue[0] = pTxDisc->type;
1838         pOutValue[1] = pTxDisc->role;
1839         pOutValue[2] = (pTxDisc->transmit_freq? 1:0);
1840         pOutValue[2] |= ((pTxDisc->duration & 0x03) << 1);
1841         memcpy(&pOutValue[4], &pTxDisc->avail_interval_bitmap,
1842                sizeof(pTxDisc->avail_interval_bitmap));
1843         tlvs = addTlv(NAN_TLV_TYPE_MAC_ADDRESS,
1844                     NAN_MAC_ADDR_LEN,
1845                     (const u8*)&pTxDisc->addr[0],
1846                     tlvs);
1847         if (pTxDisc->type == NAN_CONN_WLAN_MESH) {
1848             tlvs = addTlv(NAN_TLV_TYPE_WLAN_MESH_ID,
1849                         pTxDisc->mesh_id_len,
1850                         (const u8*)&pTxDisc->mesh_id[0],
1851                         tlvs);
1852         }
1853         if (pTxDisc->type == NAN_CONN_WLAN_INFRA) {
1854             tlvs = addTlv(NAN_TLV_TYPE_WLAN_INFRA_SSID,
1855                         pTxDisc->infrastructure_ssid_len,
1856                         (const u8*)&pTxDisc->infrastructure_ssid_val[0],
1857                         tlvs);
1858         }
1859         ALOGV("%s: Filled TransmitPostDiscoveryVal", __func__);
1860         hexdump((char*)pOutValue, calcNanTransmitPostDiscoverySize(pTxDisc));
1861     }
1862 
1863     return;
1864 }
1865 
fillNanFurtherAvailabilityMapVal(const NanFurtherAvailabilityMap * pFam,u8 * pOutValue)1866 void NanCommand::fillNanFurtherAvailabilityMapVal(
1867     const NanFurtherAvailabilityMap *pFam,
1868     u8 *pOutValue)
1869 {
1870     int idx = 0;
1871 
1872     if (pFam && pOutValue) {
1873         u32 famsize = calcNanFurtherAvailabilityMapSize(pFam);
1874         pNanFurtherAvailabilityMapAttrTlv pFwReq = \
1875             (pNanFurtherAvailabilityMapAttrTlv)pOutValue;
1876 
1877         memset(pOutValue, 0, famsize);
1878         pFwReq->numChan = pFam->numchans;
1879         for (idx = 0; idx < pFam->numchans; idx++) {
1880             const NanFurtherAvailabilityChannel *pFamChan =  \
1881                 &pFam->famchan[idx];
1882             pNanFurtherAvailabilityChan pFwFamChan = \
1883                 (pNanFurtherAvailabilityChan)((u8*)&pFwReq->pFaChan[0] + \
1884                 (idx * sizeof(NanFurtherAvailabilityChan)));
1885 
1886             pFwFamChan->entryCtrl.availIntDuration = \
1887                 pFamChan->entry_control;
1888             pFwFamChan->entryCtrl.mapId = \
1889                 pFamChan->mapid;
1890             pFwFamChan->opClass =  pFamChan->class_val;
1891             pFwFamChan->channel = pFamChan->channel;
1892             memcpy(&pFwFamChan->availIntBitmap,
1893                    &pFamChan->avail_interval_bitmap,
1894                    sizeof(pFwFamChan->availIntBitmap));
1895         }
1896         ALOGV("%s: Filled FurtherAvailabilityMapVal", __func__);
1897         hexdump((char*)pOutValue, famsize);
1898     }
1899     return;
1900 }
1901 
calcNanFurtherAvailabilityMapSize(const NanFurtherAvailabilityMap * pFam)1902 int NanCommand::calcNanFurtherAvailabilityMapSize(
1903     const NanFurtherAvailabilityMap *pFam)
1904 {
1905     int ret = 0;
1906     if (pFam && pFam->numchans &&
1907         pFam->numchans <= NAN_MAX_FAM_CHANNELS) {
1908         /* Fixed size of u8 for numchans*/
1909         ret = sizeof(u8);
1910         /* numchans * sizeof(FamChannels) */
1911         ret += (pFam->numchans * sizeof(NanFurtherAvailabilityChan));
1912     }
1913     ALOGV("%s:size:%d", __func__, ret);
1914     return ret;
1915 }
1916 
putNanCapabilities(transaction_id id)1917 wifi_error NanCommand::putNanCapabilities(transaction_id id)
1918 {
1919     wifi_error ret;
1920     ALOGV("NAN_CAPABILITIES");
1921     size_t message_len = sizeof(NanCapabilitiesReqMsg);
1922 
1923     pNanCapabilitiesReqMsg pFwReq = (pNanCapabilitiesReqMsg)malloc(message_len);
1924     if (pFwReq == NULL) {
1925         cleanup();
1926         return WIFI_ERROR_OUT_OF_MEMORY;
1927     }
1928 
1929     memset (pFwReq, 0, message_len);
1930     pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
1931     pFwReq->fwHeader.msgId = NAN_MSG_ID_CAPABILITIES_REQ;
1932     pFwReq->fwHeader.msgLen = message_len;
1933     pFwReq->fwHeader.transactionId = id;
1934 
1935     mVendorData = (char*)pFwReq;
1936     mDataLen = message_len;
1937 
1938     ret = WIFI_SUCCESS;
1939     if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
1940         ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
1941         if (ret != WIFI_SUCCESS) {
1942             ALOGE("%s: put_bytes Error:%d",__func__, ret);
1943             cleanup();
1944             return ret;
1945         }
1946     } else {
1947         struct nlattr *nl_data;
1948 
1949         nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
1950 
1951         if (!nl_data) {
1952             cleanup();
1953             return WIFI_ERROR_INVALID_ARGS;
1954         }
1955         if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
1956                              mVendorData, mDataLen)) {
1957             ALOGE("%s: put attr error", __func__);
1958             cleanup();
1959             return WIFI_ERROR_INVALID_ARGS;
1960         }
1961         attr_end(nl_data);
1962     }
1963     hexdump(mVendorData, mDataLen);
1964     return ret;
1965 }
1966 
putNanDebugCommand(NanDebugParams debug,int debug_msg_length)1967 wifi_error NanCommand::putNanDebugCommand(NanDebugParams debug,
1968                                    int debug_msg_length)
1969 {
1970     wifi_error ret;
1971     ALOGV("NAN_AVAILABILITY_DEBUG");
1972     size_t message_len = sizeof(NanTestModeReqMsg);
1973 
1974     message_len += (SIZEOF_TLV_HDR + debug_msg_length);
1975     pNanTestModeReqMsg pFwReq = (pNanTestModeReqMsg)malloc(message_len);
1976     if (pFwReq == NULL) {
1977         cleanup();
1978         return WIFI_ERROR_OUT_OF_MEMORY;
1979     }
1980 
1981     ALOGV("Message Len %zu\n", message_len);
1982     ALOGV("%s: Debug Command Type = 0x%x \n", __func__, debug.cmd);
1983     ALOGV("%s: ** Debug Command Data Start **", __func__);
1984     hexdump(debug.debug_cmd_data, debug_msg_length);
1985     ALOGV("%s: ** Debug Command Data End **", __func__);
1986 
1987     memset (pFwReq, 0, message_len);
1988     pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
1989     pFwReq->fwHeader.msgId = NAN_MSG_ID_TESTMODE_REQ;
1990     pFwReq->fwHeader.msgLen = message_len;
1991     pFwReq->fwHeader.transactionId = 0;
1992 
1993     u8* tlvs = pFwReq->ptlv;
1994     tlvs = addTlv(NAN_TLV_TYPE_TESTMODE_GENERIC_CMD, debug_msg_length,
1995                   (const u8*)&debug, tlvs);
1996 
1997     mVendorData = (char*)pFwReq;
1998     mDataLen = message_len;
1999 
2000     ret = WIFI_SUCCESS;
2001     if (mSubcmd == QCA_NL80211_VENDOR_SUBCMD_NAN) {
2002         /* Write the TLVs to the message. */
2003         ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
2004         if (ret != WIFI_SUCCESS) {
2005             ALOGE("%s: put_bytes Error:%d",__func__, ret);
2006             cleanup();
2007             return ret;
2008         }
2009     } else {
2010         struct nlattr *nl_data;
2011 
2012         nl_data = attr_start(NL80211_ATTR_VENDOR_DATA);
2013 
2014         if (!nl_data) {
2015             cleanup();
2016             return WIFI_ERROR_INVALID_ARGS;
2017         }
2018         if (mMsg.put_bytes(QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA,
2019                              mVendorData, mDataLen)) {
2020             ALOGE("%s: put attr error", __func__);
2021             cleanup();
2022             return WIFI_ERROR_INVALID_ARGS;
2023         }
2024         attr_end(nl_data);
2025     }
2026     hexdump(mVendorData, mDataLen);
2027     return ret;
2028 }
2029