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