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