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