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