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