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 ? (SIZEOF_TLV_HDR + \
108 NAN_MAX_SOCIAL_CHANNELS * 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 pNanEnableReqMsg pFwReq = (pNanEnableReqMsg)malloc(message_len);
127 if (pFwReq == NULL) {
128 cleanup();
129 return WIFI_ERROR_OUT_OF_MEMORY;
130 }
131
132 ALOGV("Message Len %zu", message_len);
133 memset (pFwReq, 0, message_len);
134 pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
135 pFwReq->fwHeader.msgId = NAN_MSG_ID_ENABLE_REQ;
136 pFwReq->fwHeader.msgLen = message_len;
137 pFwReq->fwHeader.transactionId = id;
138
139 u8* tlvs = pFwReq->ptlv;
140
141 /* Write the TLVs to the message. */
142
143 tlvs = addTlv(NAN_TLV_TYPE_CLUSTER_ID_LOW, sizeof(pReq->cluster_low),
144 (const u8*)&pReq->cluster_low, tlvs);
145 tlvs = addTlv(NAN_TLV_TYPE_CLUSTER_ID_HIGH, sizeof(pReq->cluster_high),
146 (const u8*)&pReq->cluster_high, tlvs);
147 tlvs = addTlv(NAN_TLV_TYPE_MASTER_PREFERENCE, sizeof(pReq->master_pref),
148 (const u8*)&pReq->master_pref, tlvs);
149 if (pReq->config_support_5g) {
150 tlvs = addTlv(NAN_TLV_TYPE_5G_SUPPORT, sizeof(pReq->support_5g_val),
151 (const u8*)&pReq->support_5g_val, tlvs);
152 }
153 if (pReq->config_sid_beacon) {
154 tlvs = addTlv(NAN_TLV_TYPE_SID_BEACON, sizeof(pReq->sid_beacon_val),
155 (const u8*)&pReq->sid_beacon_val, tlvs);
156 }
157 if (pReq->config_2dot4g_rssi_close) {
158 tlvs = addTlv(NAN_TLV_TYPE_24G_RSSI_CLOSE,
159 sizeof(pReq->rssi_close_2dot4g_val),
160 (const u8*)&pReq->rssi_close_2dot4g_val, tlvs);
161 }
162 if (pReq->config_2dot4g_rssi_middle) {
163 tlvs = addTlv(NAN_TLV_TYPE_24G_RSSI_MIDDLE,
164 sizeof(pReq->rssi_middle_2dot4g_val),
165 (const u8*)&pReq->rssi_middle_2dot4g_val, tlvs);
166 }
167 if (pReq->config_hop_count_limit) {
168 tlvs = addTlv(NAN_TLV_TYPE_HOP_COUNT_LIMIT,
169 sizeof(pReq->hop_count_limit_val),
170 (const u8*)&pReq->hop_count_limit_val, tlvs);
171 }
172 if (pReq->config_2dot4g_support) {
173 tlvs = addTlv(NAN_TLV_TYPE_24G_SUPPORT, sizeof(pReq->support_2dot4g_val),
174 (const u8*)&pReq->support_2dot4g_val, tlvs);
175 }
176 if (pReq->config_2dot4g_beacons) {
177 tlvs = addTlv(NAN_TLV_TYPE_24G_BEACON, sizeof(pReq->beacon_2dot4g_val),
178 (const u8*)&pReq->beacon_2dot4g_val, tlvs);
179 }
180 if (pReq->config_2dot4g_sdf) {
181 tlvs = addTlv(NAN_TLV_TYPE_24G_SDF, sizeof(pReq->sdf_2dot4g_val),
182 (const u8*)&pReq->sdf_2dot4g_val, tlvs);
183 }
184 if (pReq->config_5g_beacons) {
185 tlvs = addTlv(NAN_TLV_TYPE_5G_BEACON, sizeof(pReq->beacon_5g_val),
186 (const u8*)&pReq->beacon_5g_val, tlvs);
187 }
188 if (pReq->config_5g_sdf) {
189 tlvs = addTlv(NAN_TLV_TYPE_5G_SDF, sizeof(pReq->sdf_5g_val),
190 (const u8*)&pReq->sdf_5g_val, tlvs);
191 }
192 if (pReq->config_2dot4g_rssi_proximity) {
193 tlvs = addTlv(NAN_TLV_TYPE_24G_RSSI_CLOSE_PROXIMITY,
194 sizeof(pReq->rssi_proximity_2dot4g_val),
195 (const u8*)&pReq->rssi_proximity_2dot4g_val, tlvs);
196 }
197 /* Add the support of sending 5G RSSI values */
198 if (pReq->config_5g_rssi_close) {
199 tlvs = addTlv(NAN_TLV_TYPE_5G_RSSI_CLOSE, sizeof(pReq->rssi_close_5g_val),
200 (const u8*)&pReq->rssi_close_5g_val, tlvs);
201 }
202 if (pReq->config_5g_rssi_middle) {
203 tlvs = addTlv(NAN_TLV_TYPE_5G_RSSI_MIDDLE, sizeof(pReq->rssi_middle_5g_val),
204 (const u8*)&pReq->rssi_middle_5g_val, tlvs);
205 }
206 if (pReq->config_5g_rssi_close_proximity) {
207 tlvs = addTlv(NAN_TLV_TYPE_5G_RSSI_CLOSE_PROXIMITY,
208 sizeof(pReq->rssi_close_proximity_5g_val),
209 (const u8*)&pReq->rssi_close_proximity_5g_val, tlvs);
210 }
211 if (pReq->config_rssi_window_size) {
212 tlvs = addTlv(NAN_TLV_TYPE_RSSI_AVERAGING_WINDOW_SIZE, sizeof(pReq->rssi_window_size_val),
213 (const u8*)&pReq->rssi_window_size_val, tlvs);
214 }
215 if (pReq->config_oui) {
216 tlvs = addTlv(NAN_TLV_TYPE_CLUSTER_OUI_NETWORK_ID, sizeof(pReq->oui_val),
217 (const u8*)&pReq->oui_val, tlvs);
218 }
219 if (pReq->config_intf_addr) {
220 tlvs = addTlv(NAN_TLV_TYPE_SOURCE_MAC_ADDRESS, sizeof(pReq->intf_addr_val),
221 (const u8*)&pReq->intf_addr_val[0], tlvs);
222 }
223 if (pReq->config_cluster_attribute_val) {
224 tlvs = addTlv(NAN_TLV_TYPE_CLUSTER_ATTRIBUTE_IN_SDF, sizeof(pReq->config_cluster_attribute_val),
225 (const u8*)&pReq->config_cluster_attribute_val, tlvs);
226 }
227 if (pReq->config_scan_params) {
228 u32 socialChannelParamVal[NAN_MAX_SOCIAL_CHANNELS];
229 /* Fill the social channel param */
230 fillNanSocialChannelParamVal(&pReq->scan_params_val,
231 socialChannelParamVal);
232 int i;
233 for (i = 0; i < NAN_MAX_SOCIAL_CHANNELS; i++) {
234 tlvs = addTlv(NAN_TLV_TYPE_SOCIAL_CHANNEL_SCAN_PARAMS,
235 sizeof(socialChannelParamVal[i]),
236 (const u8*)&socialChannelParamVal[i], tlvs);
237 }
238 }
239 if (pReq->config_random_factor_force) {
240 tlvs = addTlv(NAN_TLV_TYPE_RANDOM_FACTOR_FORCE,
241 sizeof(pReq->random_factor_force_val),
242 (const u8*)&pReq->random_factor_force_val, tlvs);
243 }
244 if (pReq->config_hop_count_force) {
245 tlvs = addTlv(NAN_TLV_TYPE_HOP_COUNT_FORCE,
246 sizeof(pReq->hop_count_force_val),
247 (const u8*)&pReq->hop_count_force_val, tlvs);
248 }
249 if (pReq->config_24g_channel) {
250 tlvs = addTlv(NAN_TLV_TYPE_24G_CHANNEL,
251 sizeof(u32),
252 (const u8*)&pReq->channel_24g_val, tlvs);
253 }
254 if (pReq->config_5g_channel) {
255 tlvs = addTlv(NAN_TLV_TYPE_5G_CHANNEL,
256 sizeof(u32),
257 (const u8*)&pReq->channel_5g_val, tlvs);
258 }
259 mVendorData = (char*)pFwReq;
260 mDataLen = message_len;
261
262 //Insert the vendor specific data
263 int ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
264 if (ret < 0) {
265 ALOGE("%s: put_bytes Error:%d",__func__, ret);
266 cleanup();
267 return ret;
268 }
269 hexdump(mVendorData, mDataLen);
270 return ret;
271 }
272
putNanDisable(transaction_id id)273 int NanCommand::putNanDisable(transaction_id id)
274 {
275 ALOGV("NAN_DISABLE");
276 size_t message_len = sizeof(NanDisableReqMsg);
277
278 pNanDisableReqMsg pFwReq = (pNanDisableReqMsg)malloc(message_len);
279 if (pFwReq == NULL) {
280 cleanup();
281 return WIFI_ERROR_OUT_OF_MEMORY;
282 }
283
284 ALOGV("Message Len %zu", message_len);
285 memset (pFwReq, 0, message_len);
286 pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
287 pFwReq->fwHeader.msgId = NAN_MSG_ID_DISABLE_REQ;
288 pFwReq->fwHeader.msgLen = message_len;
289 pFwReq->fwHeader.transactionId = id;
290
291 mVendorData = (char*)pFwReq;
292 mDataLen = message_len;
293
294 int ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
295 if (ret < 0) {
296 ALOGE("%s: put_bytes Error:%d",__func__, ret);
297 cleanup();
298 return ret;
299 }
300 hexdump(mVendorData, mDataLen);
301 return ret;
302 }
303
putNanConfig(transaction_id id,const NanConfigRequest * pReq)304 int NanCommand::putNanConfig(transaction_id id, const NanConfigRequest *pReq)
305 {
306 ALOGV("NAN_CONFIG");
307 size_t message_len = NAN_MAX_CONFIGURATION_REQ_SIZE;
308 int idx = 0;
309
310 if (pReq == NULL ||
311 pReq->num_config_discovery_attr > NAN_MAX_POSTDISCOVERY_LEN) {
312 cleanup();
313 return WIFI_ERROR_INVALID_ARGS;
314 }
315
316 message_len = sizeof(NanMsgHeader);
317
318 message_len += \
319 (
320 pReq->config_sid_beacon ? (SIZEOF_TLV_HDR + \
321 sizeof(pReq->sid_beacon)) : 0 \
322 ) + \
323 (
324 pReq->config_master_pref ? (SIZEOF_TLV_HDR + \
325 sizeof(pReq->master_pref)) : 0 \
326 ) + \
327 (
328 pReq->config_rssi_proximity ? (SIZEOF_TLV_HDR + \
329 sizeof(pReq->rssi_proximity)) : 0 \
330 ) + \
331 (
332 pReq->config_5g_rssi_close_proximity ? (SIZEOF_TLV_HDR + \
333 sizeof(pReq->rssi_close_proximity_5g_val)) : 0 \
334 ) + \
335 (
336 pReq->config_rssi_window_size ? (SIZEOF_TLV_HDR + \
337 sizeof(pReq->rssi_window_size_val)) : 0 \
338 ) + \
339 (
340 pReq->config_cluster_attribute_val ? (SIZEOF_TLV_HDR + \
341 sizeof(pReq->config_cluster_attribute_val)) : 0 \
342 ) + \
343 (
344 pReq->config_scan_params ? (SIZEOF_TLV_HDR + \
345 NAN_MAX_SOCIAL_CHANNELS * sizeof(u32)) : 0 \
346 ) + \
347 (
348 pReq->config_random_factor_force ? (SIZEOF_TLV_HDR + \
349 sizeof(pReq->random_factor_force_val)) : 0 \
350 ) + \
351 (
352 pReq->config_hop_count_force ? (SIZEOF_TLV_HDR + \
353 sizeof(pReq->hop_count_force_val)) : 0 \
354 ) + \
355 (
356 pReq->config_conn_capability ? (SIZEOF_TLV_HDR + \
357 sizeof(u32)) : 0 \
358 );
359
360 if (pReq->num_config_discovery_attr) {
361 for (idx = 0; idx < pReq->num_config_discovery_attr; idx ++) {
362 message_len += SIZEOF_TLV_HDR +\
363 calcNanTransmitPostDiscoverySize(&pReq->discovery_attr_val[idx]);
364 }
365 }
366
367 if (pReq->config_fam && \
368 calcNanFurtherAvailabilityMapSize(&pReq->fam_val)) {
369 message_len += (SIZEOF_TLV_HDR + \
370 calcNanFurtherAvailabilityMapSize(&pReq->fam_val));
371 }
372
373 pNanConfigurationReqMsg pFwReq = (pNanConfigurationReqMsg)malloc(message_len);
374 if (pFwReq == NULL) {
375 cleanup();
376 return WIFI_ERROR_OUT_OF_MEMORY;
377 }
378
379 ALOGV("Message Len %zu", message_len);
380 memset (pFwReq, 0, message_len);
381 pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
382 pFwReq->fwHeader.msgId = NAN_MSG_ID_CONFIGURATION_REQ;
383 pFwReq->fwHeader.msgLen = message_len;
384 pFwReq->fwHeader.transactionId = id;
385
386 u8* tlvs = pFwReq->ptlv;
387 if (pReq->config_sid_beacon) {
388 tlvs = addTlv(NAN_TLV_TYPE_SID_BEACON, sizeof(pReq->sid_beacon),
389 (const u8*)&pReq->sid_beacon, tlvs);
390 }
391 if (pReq->config_master_pref) {
392 tlvs = addTlv(NAN_TLV_TYPE_MASTER_PREFERENCE, sizeof(pReq->master_pref),
393 (const u8*)&pReq->master_pref, tlvs);
394 }
395
396 if (pReq->config_rssi_window_size) {
397 tlvs = addTlv(NAN_TLV_TYPE_RSSI_AVERAGING_WINDOW_SIZE, sizeof(pReq->rssi_window_size_val),
398 (const u8*)&pReq->rssi_window_size_val, tlvs);
399 }
400 if (pReq->config_rssi_proximity) {
401 tlvs = addTlv(NAN_TLV_TYPE_24G_RSSI_CLOSE_PROXIMITY, sizeof(pReq->rssi_proximity),
402 (const u8*)&pReq->rssi_proximity, tlvs);
403 }
404 if (pReq->config_scan_params) {
405 u32 socialChannelParamVal[NAN_MAX_SOCIAL_CHANNELS];
406 /* Fill the social channel param */
407 fillNanSocialChannelParamVal(&pReq->scan_params_val,
408 socialChannelParamVal);
409 int i;
410 for (i = 0; i < NAN_MAX_SOCIAL_CHANNELS; i++) {
411 tlvs = addTlv(NAN_TLV_TYPE_SOCIAL_CHANNEL_SCAN_PARAMS,
412 sizeof(socialChannelParamVal[i]),
413 (const u8*)&socialChannelParamVal[i], tlvs);
414 }
415 }
416 if (pReq->config_random_factor_force) {
417 tlvs = addTlv(NAN_TLV_TYPE_RANDOM_FACTOR_FORCE,
418 sizeof(pReq->random_factor_force_val),
419 (const u8*)&pReq->random_factor_force_val, tlvs);
420 }
421 if (pReq->config_hop_count_force) {
422 tlvs = addTlv(NAN_TLV_TYPE_HOP_COUNT_FORCE,
423 sizeof(pReq->hop_count_force_val),
424 (const u8*)&pReq->hop_count_force_val, tlvs);
425 }
426 if (pReq->config_conn_capability) {
427 u32 val = \
428 getNanTransmitPostConnectivityCapabilityVal(&pReq->conn_capability_val);
429 tlvs = addTlv(NAN_TLV_TYPE_POST_NAN_CONNECTIVITY_CAPABILITIES_TRANSMIT,
430 sizeof(val), (const u8*)&val, tlvs);
431 }
432 if (pReq->num_config_discovery_attr) {
433 for (idx = 0; idx < pReq->num_config_discovery_attr; idx ++) {
434 fillNanTransmitPostDiscoveryVal(&pReq->discovery_attr_val[idx],
435 (u8*)(tlvs + SIZEOF_TLV_HDR));
436 tlvs = addTlv(NAN_TLV_TYPE_POST_NAN_DISCOVERY_ATTRIBUTE_TRANSMIT,
437 calcNanTransmitPostDiscoverySize(
438 &pReq->discovery_attr_val[idx]),
439 (const u8*)(tlvs + SIZEOF_TLV_HDR), tlvs);
440 }
441 }
442 if (pReq->config_fam && \
443 calcNanFurtherAvailabilityMapSize(&pReq->fam_val)) {
444 fillNanFurtherAvailabilityMapVal(&pReq->fam_val,
445 (u8*)(tlvs + SIZEOF_TLV_HDR));
446 tlvs = addTlv(NAN_TLV_TYPE_FURTHER_AVAILABILITY_MAP,
447 calcNanFurtherAvailabilityMapSize(&pReq->fam_val),
448 (const u8*)(tlvs + SIZEOF_TLV_HDR), tlvs);
449 }
450
451 mVendorData = (char*)pFwReq;
452 mDataLen = message_len;
453
454 int ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
455 if (ret < 0) {
456 ALOGE("%s: put_bytes Error:%d",__func__, ret);
457 cleanup();
458 return ret;
459 }
460 hexdump(mVendorData, mDataLen);
461 return ret;
462 }
463
464
putNanPublish(transaction_id id,const NanPublishRequest * pReq)465 int NanCommand::putNanPublish(transaction_id id, const NanPublishRequest *pReq)
466 {
467 ALOGV("NAN_PUBLISH");
468 if (pReq == NULL) {
469 cleanup();
470 return WIFI_ERROR_INVALID_ARGS;
471 }
472
473 size_t message_len =
474 sizeof(NanMsgHeader) + sizeof(NanPublishServiceReqParams) +
475 (pReq->service_name_len ? SIZEOF_TLV_HDR + pReq->service_name_len : 0) +
476 (pReq->service_specific_info_len ? SIZEOF_TLV_HDR + pReq->service_specific_info_len : 0) +
477 (pReq->rx_match_filter_len ? SIZEOF_TLV_HDR + pReq->rx_match_filter_len : 0) +
478 (pReq->tx_match_filter_len ? SIZEOF_TLV_HDR + pReq->tx_match_filter_len : 0);
479
480 pNanPublishServiceReqMsg pFwReq = (pNanPublishServiceReqMsg)malloc(message_len);
481 if (pFwReq == NULL) {
482 cleanup();
483 return WIFI_ERROR_OUT_OF_MEMORY;
484 }
485
486 ALOGV("Message Len %zu", message_len);
487 memset(pFwReq, 0, message_len);
488 pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
489 pFwReq->fwHeader.msgId = NAN_MSG_ID_PUBLISH_SERVICE_REQ;
490 pFwReq->fwHeader.msgLen = message_len;
491 if (pReq->publish_id == 0) {
492 pFwReq->fwHeader.handle = 0xFFFF;
493 } else {
494 pFwReq->fwHeader.handle = pReq->publish_id;
495 }
496 pFwReq->fwHeader.transactionId = id;
497
498 pFwReq->publishServiceReqParams.ttl = pReq->ttl;
499 pFwReq->publishServiceReqParams.period = pReq->period;
500 pFwReq->publishServiceReqParams.reserved = 0;
501 pFwReq->publishServiceReqParams.publishType = pReq->publish_type;
502 pFwReq->publishServiceReqParams.txType = pReq->tx_type;
503
504 pFwReq->publishServiceReqParams.rssiThresholdFlag = pReq->rssi_threshold_flag;
505 pFwReq->publishServiceReqParams.matchAlg = pReq->publish_match_indicator;
506 pFwReq->publishServiceReqParams.count = pReq->publish_count;
507 pFwReq->publishServiceReqParams.connmap = pReq->connmap;
508 pFwReq->publishServiceReqParams.pubTerminatedIndDisableFlag =
509 (pReq->recv_indication_cfg & BIT_0) ? 1 : 0;
510 pFwReq->publishServiceReqParams.pubMatchExpiredIndDisableFlag =
511 (pReq->recv_indication_cfg & BIT_1) ? 1 : 0;
512 pFwReq->publishServiceReqParams.followupRxIndDisableFlag =
513 (pReq->recv_indication_cfg & BIT_2) ? 1 : 0;
514
515 pFwReq->publishServiceReqParams.reserved2 = 0;
516
517 u8* tlvs = pFwReq->ptlv;
518 if (pReq->service_name_len) {
519 tlvs = addTlv(NAN_TLV_TYPE_SERVICE_NAME, pReq->service_name_len,
520 (const u8*)&pReq->service_name[0], tlvs);
521 }
522 if (pReq->service_specific_info_len) {
523 tlvs = addTlv(NAN_TLV_TYPE_SERVICE_SPECIFIC_INFO, pReq->service_specific_info_len,
524 (const u8*)&pReq->service_specific_info[0], tlvs);
525 }
526 if (pReq->rx_match_filter_len) {
527 tlvs = addTlv(NAN_TLV_TYPE_RX_MATCH_FILTER, pReq->rx_match_filter_len,
528 (const u8*)&pReq->rx_match_filter[0], tlvs);
529 }
530 if (pReq->tx_match_filter_len) {
531 tlvs = addTlv(NAN_TLV_TYPE_TX_MATCH_FILTER, pReq->tx_match_filter_len,
532 (const u8*)&pReq->tx_match_filter[0], tlvs);
533 }
534
535 mVendorData = (char *)pFwReq;
536 mDataLen = message_len;
537
538 int ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
539 if (ret < 0) {
540 ALOGE("%s: put_bytes Error:%d",__func__, ret);
541 cleanup();
542 return ret;
543 }
544 hexdump(mVendorData, mDataLen);
545 return ret;
546 }
547
putNanPublishCancel(transaction_id id,const NanPublishCancelRequest * pReq)548 int NanCommand::putNanPublishCancel(transaction_id id, const NanPublishCancelRequest *pReq)
549 {
550 ALOGV("NAN_PUBLISH_CANCEL");
551 if (pReq == NULL) {
552 cleanup();
553 return WIFI_ERROR_INVALID_ARGS;
554 }
555 size_t message_len = sizeof(NanPublishServiceCancelReqMsg);
556
557 pNanPublishServiceCancelReqMsg pFwReq =
558 (pNanPublishServiceCancelReqMsg)malloc(message_len);
559 if (pFwReq == NULL) {
560 cleanup();
561 return WIFI_ERROR_OUT_OF_MEMORY;
562 }
563
564 ALOGV("Message Len %zu", message_len);
565 memset(pFwReq, 0, message_len);
566 pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
567 pFwReq->fwHeader.msgId = NAN_MSG_ID_PUBLISH_SERVICE_CANCEL_REQ;
568 pFwReq->fwHeader.msgLen = message_len;
569 pFwReq->fwHeader.handle = pReq->publish_id;
570 pFwReq->fwHeader.transactionId = id;
571
572 mVendorData = (char *)pFwReq;
573 mDataLen = message_len;
574
575 int ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
576 if (ret < 0) {
577 ALOGE("%s: put_bytes Error:%d",__func__, ret);
578 cleanup();
579 return ret;
580 }
581 hexdump(mVendorData, mDataLen);
582 return ret;
583 }
584
putNanSubscribe(transaction_id id,const NanSubscribeRequest * pReq)585 int NanCommand::putNanSubscribe(transaction_id id,
586 const NanSubscribeRequest *pReq)
587 {
588
589 ALOGV("NAN_SUBSCRIBE");
590 if (pReq == NULL) {
591 cleanup();
592 return WIFI_ERROR_INVALID_ARGS;
593 }
594
595 size_t message_len =
596 sizeof(NanMsgHeader) + sizeof(NanSubscribeServiceReqParams) +
597 (pReq->service_name_len ? SIZEOF_TLV_HDR + pReq->service_name_len : 0) +
598 (pReq->service_specific_info_len ? SIZEOF_TLV_HDR + pReq->service_specific_info_len : 0) +
599 (pReq->rx_match_filter_len ? SIZEOF_TLV_HDR + pReq->rx_match_filter_len : 0) +
600 (pReq->tx_match_filter_len ? SIZEOF_TLV_HDR + pReq->tx_match_filter_len : 0);
601
602 message_len += \
603 (pReq->num_intf_addr_present * (SIZEOF_TLV_HDR + NAN_MAC_ADDR_LEN));
604
605 pNanSubscribeServiceReqMsg pFwReq = (pNanSubscribeServiceReqMsg)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_SUBSCRIBE_SERVICE_REQ;
615 pFwReq->fwHeader.msgLen = message_len;
616 if (pReq->subscribe_id == 0) {
617 pFwReq->fwHeader.handle = 0xFFFF;
618 } else {
619 pFwReq->fwHeader.handle = pReq->subscribe_id;
620 }
621 pFwReq->fwHeader.transactionId = id;
622
623 pFwReq->subscribeServiceReqParams.ttl = pReq->ttl;
624 pFwReq->subscribeServiceReqParams.period = pReq->period;
625 pFwReq->subscribeServiceReqParams.subscribeType = pReq->subscribe_type;
626 pFwReq->subscribeServiceReqParams.srfAttr = pReq->serviceResponseFilter;
627 pFwReq->subscribeServiceReqParams.srfInclude = pReq->serviceResponseInclude;
628 pFwReq->subscribeServiceReqParams.srfSend = pReq->useServiceResponseFilter;
629 pFwReq->subscribeServiceReqParams.ssiRequired = pReq->ssiRequiredForMatchIndication;
630 pFwReq->subscribeServiceReqParams.matchAlg = pReq->subscribe_match_indicator;
631 pFwReq->subscribeServiceReqParams.count = pReq->subscribe_count;
632 pFwReq->subscribeServiceReqParams.rssiThresholdFlag = pReq->rssi_threshold_flag;
633 pFwReq->subscribeServiceReqParams.subTerminatedIndDisableFlag =
634 (pReq->recv_indication_cfg & BIT_0) ? 1 : 0;
635 pFwReq->subscribeServiceReqParams.subMatchExpiredIndDisableFlag =
636 (pReq->recv_indication_cfg & BIT_1) ? 1 : 0;
637 pFwReq->subscribeServiceReqParams.followupRxIndDisableFlag =
638 (pReq->recv_indication_cfg & BIT_2) ? 1 : 0;
639 pFwReq->subscribeServiceReqParams.connmap = pReq->connmap;
640 pFwReq->subscribeServiceReqParams.reserved = 0;
641
642 u8* tlvs = pFwReq->ptlv;
643 if (pReq->service_name_len) {
644 tlvs = addTlv(NAN_TLV_TYPE_SERVICE_NAME, pReq->service_name_len,
645 (const u8*)&pReq->service_name[0], tlvs);
646 }
647 if (pReq->service_specific_info_len) {
648 tlvs = addTlv(NAN_TLV_TYPE_SERVICE_SPECIFIC_INFO, pReq->service_specific_info_len,
649 (const u8*)&pReq->service_specific_info[0], tlvs);
650 }
651 if (pReq->rx_match_filter_len) {
652 tlvs = addTlv(NAN_TLV_TYPE_RX_MATCH_FILTER, pReq->rx_match_filter_len,
653 (const u8*)&pReq->rx_match_filter[0], tlvs);
654 }
655 if (pReq->tx_match_filter_len) {
656 tlvs = addTlv(NAN_TLV_TYPE_TX_MATCH_FILTER, pReq->tx_match_filter_len,
657 (const u8*)&pReq->tx_match_filter[0], tlvs);
658 }
659
660 int i = 0;
661 for (i = 0; i < pReq->num_intf_addr_present; i++)
662 {
663 tlvs = addTlv(NAN_TLV_TYPE_MAC_ADDRESS,
664 NAN_MAC_ADDR_LEN,
665 (const u8*)&pReq->intf_addr[i][0], tlvs);
666 }
667
668 mVendorData = (char *)pFwReq;
669 mDataLen = message_len;
670 int ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
671 if (ret < 0) {
672 ALOGE("%s: put_bytes Error:%d",__func__, ret);
673 cleanup();
674 return ret;
675 }
676 hexdump(mVendorData, mDataLen);
677 return ret;
678 }
679
putNanSubscribeCancel(transaction_id id,const NanSubscribeCancelRequest * pReq)680 int NanCommand::putNanSubscribeCancel(transaction_id id,
681 const NanSubscribeCancelRequest *pReq)
682 {
683 ALOGV("NAN_SUBSCRIBE_CANCEL");
684 if (pReq == NULL) {
685 cleanup();
686 return WIFI_ERROR_INVALID_ARGS;
687 }
688 size_t message_len = sizeof(NanSubscribeServiceCancelReqMsg);
689
690 pNanSubscribeServiceCancelReqMsg pFwReq =
691 (pNanSubscribeServiceCancelReqMsg)malloc(message_len);
692 if (pFwReq == NULL) {
693 cleanup();
694 return WIFI_ERROR_OUT_OF_MEMORY;
695 }
696
697 ALOGV("Message Len %zu", message_len);
698 memset(pFwReq, 0, message_len);
699 pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
700 pFwReq->fwHeader.msgId = NAN_MSG_ID_SUBSCRIBE_SERVICE_CANCEL_REQ;
701 pFwReq->fwHeader.msgLen = message_len;
702 pFwReq->fwHeader.handle = pReq->subscribe_id;
703 pFwReq->fwHeader.transactionId = id;
704
705 mVendorData = (char *)pFwReq;
706 mDataLen = message_len;
707 int ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
708 if (ret < 0) {
709 ALOGE("%s: put_bytes Error:%d",__func__, ret);
710 cleanup();
711 return ret;
712 }
713 hexdump(mVendorData, mDataLen);
714 return ret;
715 }
716
717
putNanTransmitFollowup(transaction_id id,const NanTransmitFollowupRequest * pReq)718 int NanCommand::putNanTransmitFollowup(transaction_id id,
719 const NanTransmitFollowupRequest *pReq)
720 {
721 ALOGV("TRANSMIT_FOLLOWUP");
722 if (pReq == NULL) {
723 cleanup();
724 return WIFI_ERROR_INVALID_ARGS;
725 }
726
727 size_t message_len =
728 sizeof(NanMsgHeader) + sizeof(NanTransmitFollowupReqParams) +
729 (pReq->service_specific_info_len ? SIZEOF_TLV_HDR +
730 pReq->service_specific_info_len : 0);
731
732 /* Mac address needs to be added in TLV */
733 message_len += (SIZEOF_TLV_HDR + sizeof(pReq->addr));
734
735 pNanTransmitFollowupReqMsg pFwReq = (pNanTransmitFollowupReqMsg)malloc(message_len);
736 if (pFwReq == NULL) {
737 cleanup();
738 return WIFI_ERROR_OUT_OF_MEMORY;
739 }
740
741 ALOGV("Message Len %zu", message_len);
742 memset (pFwReq, 0, message_len);
743 pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
744 pFwReq->fwHeader.msgId = NAN_MSG_ID_TRANSMIT_FOLLOWUP_REQ;
745 pFwReq->fwHeader.msgLen = message_len;
746 pFwReq->fwHeader.handle = pReq->publish_subscribe_id;
747 pFwReq->fwHeader.transactionId = id;
748
749 pFwReq->transmitFollowupReqParams.matchHandle = pReq->requestor_instance_id;
750 if (pReq->priority != NAN_TX_PRIORITY_HIGH) {
751 pFwReq->transmitFollowupReqParams.priority = 1;
752 } else {
753 pFwReq->transmitFollowupReqParams.priority = 2;
754 }
755 pFwReq->transmitFollowupReqParams.window = pReq->dw_or_faw;
756 pFwReq->transmitFollowupReqParams.followupTxRspDisableFlag =
757 (pReq->recv_indication_cfg & BIT_0) ? 1 : 0;
758 pFwReq->transmitFollowupReqParams.reserved = 0;
759
760 u8* tlvs = pFwReq->ptlv;
761
762 /* Mac address needs to be added in TLV */
763 tlvs = addTlv(NAN_TLV_TYPE_MAC_ADDRESS, sizeof(pReq->addr),
764 (const u8*)&pReq->addr[0], tlvs);
765 u16 tlv_type = NAN_TLV_TYPE_SERVICE_SPECIFIC_INFO;
766
767 if (pReq->service_specific_info_len) {
768 tlvs = addTlv(tlv_type, pReq->service_specific_info_len,
769 (const u8*)&pReq->service_specific_info[0], tlvs);
770 }
771
772 mVendorData = (char *)pFwReq;
773 mDataLen = message_len;
774
775 int ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
776 if (ret < 0) {
777 ALOGE("%s: put_bytes Error:%d",__func__, ret);
778 cleanup();
779 return ret;
780 }
781 hexdump(mVendorData, mDataLen);
782 return ret;
783 }
784
putNanStats(transaction_id id,const NanStatsRequest * pReq)785 int NanCommand::putNanStats(transaction_id id, const NanStatsRequest *pReq)
786 {
787 ALOGV("NAN_STATS");
788 if (pReq == NULL) {
789 cleanup();
790 return WIFI_ERROR_INVALID_ARGS;
791 }
792 size_t message_len = sizeof(NanStatsReqMsg);
793
794 pNanStatsReqMsg pFwReq =
795 (pNanStatsReqMsg)malloc(message_len);
796 if (pFwReq == NULL) {
797 cleanup();
798 return WIFI_ERROR_OUT_OF_MEMORY;
799 }
800
801 ALOGV("Message Len %zu", message_len);
802 memset(pFwReq, 0, message_len);
803 pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
804 pFwReq->fwHeader.msgId = NAN_MSG_ID_STATS_REQ;
805 pFwReq->fwHeader.msgLen = message_len;
806 pFwReq->fwHeader.transactionId = id;
807
808 pFwReq->statsReqParams.statsType = pReq->stats_type;
809 pFwReq->statsReqParams.clear = pReq->clear;
810 pFwReq->statsReqParams.reserved = 0;
811
812 mVendorData = (char *)pFwReq;
813 mDataLen = message_len;
814
815 int ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
816 if (ret < 0) {
817 ALOGE("%s: put_bytes Error:%d",__func__, ret);
818 cleanup();
819 return ret;
820 }
821 hexdump(mVendorData, mDataLen);
822 return ret;
823 }
824
putNanTCA(transaction_id id,const NanTCARequest * pReq)825 int NanCommand::putNanTCA(transaction_id id, const NanTCARequest *pReq)
826 {
827 ALOGV("NAN_TCA");
828 if (pReq == NULL) {
829 cleanup();
830 return WIFI_ERROR_INVALID_ARGS;
831 }
832 size_t message_len = sizeof(NanTcaReqMsg);
833
834 message_len += (SIZEOF_TLV_HDR + 2 * sizeof(u32));
835 pNanTcaReqMsg pFwReq =
836 (pNanTcaReqMsg)malloc(message_len);
837 if (pFwReq == NULL) {
838 cleanup();
839 return WIFI_ERROR_OUT_OF_MEMORY;
840 }
841
842 ALOGV("Message Len %zu", message_len);
843 memset(pFwReq, 0, message_len);
844 pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
845 pFwReq->fwHeader.msgId = NAN_MSG_ID_TCA_REQ;
846 pFwReq->fwHeader.msgLen = message_len;
847 pFwReq->fwHeader.transactionId = id;
848
849 u32 tcaReqParams[2];
850 memset (tcaReqParams, 0, sizeof(tcaReqParams));
851 tcaReqParams[0] = (pReq->rising_direction_evt_flag & 0x01);
852 tcaReqParams[0] |= (pReq->falling_direction_evt_flag & 0x01) << 1;
853 tcaReqParams[0] |= (pReq->clear & 0x01) << 2;
854 tcaReqParams[1] = pReq->threshold;
855
856 u8* tlvs = pFwReq->ptlv;
857
858 if (pReq->tca_type == NAN_TCA_ID_CLUSTER_SIZE) {
859 tlvs = addTlv(NAN_TLV_TYPE_CLUSTER_SIZE_REQ, sizeof(tcaReqParams),
860 (const u8*)&tcaReqParams[0], tlvs);
861 }
862 else {
863 ALOGE("%s: Unrecognized tca_type:%u", __FUNCTION__, pReq->tca_type);
864 cleanup();
865 return WIFI_ERROR_INVALID_ARGS;
866 }
867
868 mVendorData = (char *)pFwReq;
869 mDataLen = message_len;
870
871 int ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
872 if (ret < 0) {
873 ALOGE("%s: put_bytes Error:%d",__func__, ret);
874 cleanup();
875 return ret;
876 }
877 hexdump(mVendorData, mDataLen);
878 return ret;
879 }
880
putNanBeaconSdfPayload(transaction_id id,const NanBeaconSdfPayloadRequest * pReq)881 int NanCommand::putNanBeaconSdfPayload(transaction_id id,
882 const NanBeaconSdfPayloadRequest *pReq)
883 {
884 ALOGV("NAN_BEACON_SDF_PAYLAOD");
885 if (pReq == NULL) {
886 cleanup();
887 return WIFI_ERROR_INVALID_ARGS;
888 }
889 size_t message_len = sizeof(NanMsgHeader) + \
890 SIZEOF_TLV_HDR + sizeof(u32) + \
891 pReq->vsa.vsa_len;
892
893 pNanBeaconSdfPayloadReqMsg pFwReq =
894 (pNanBeaconSdfPayloadReqMsg)malloc(message_len);
895 if (pFwReq == NULL) {
896 cleanup();
897 return WIFI_ERROR_OUT_OF_MEMORY;
898 }
899
900 ALOGV("Message Len %zu", message_len);
901 memset(pFwReq, 0, message_len);
902 pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
903 pFwReq->fwHeader.msgId = NAN_MSG_ID_BEACON_SDF_REQ;
904 pFwReq->fwHeader.msgLen = message_len;
905 pFwReq->fwHeader.transactionId = id;
906
907 /* Construct First 4 bytes of NanBeaconSdfPayloadReqMsg */
908 u32 temp = 0;
909 temp = pReq->vsa.payload_transmit_flag & 0x01;
910 temp |= (pReq->vsa.tx_in_discovery_beacon & 0x01) << 1;
911 temp |= (pReq->vsa.tx_in_sync_beacon & 0x01) << 2;
912 temp |= (pReq->vsa.tx_in_service_discovery & 0x01) << 3;
913 temp |= (pReq->vsa.vendor_oui & 0x00FFFFFF) << 8;
914
915 int tlv_len = sizeof(u32) + pReq->vsa.vsa_len;
916 u8* tempBuf = (u8*)malloc(tlv_len);
917 if (tempBuf == NULL) {
918 ALOGE("%s: Malloc failed", __func__);
919 free(pFwReq);
920 cleanup();
921 return WIFI_ERROR_OUT_OF_MEMORY;
922 }
923 memset(tempBuf, 0, tlv_len);
924 memcpy(tempBuf, &temp, sizeof(u32));
925 memcpy((tempBuf + sizeof(u32)), pReq->vsa.vsa, pReq->vsa.vsa_len);
926
927 u8* tlvs = pFwReq->ptlv;
928
929 /* Write the TLVs to the message. */
930 tlvs = addTlv(NAN_TLV_TYPE_VENDOR_SPECIFIC_ATTRIBUTE_TRANSMIT, tlv_len,
931 (const u8*)tempBuf, tlvs);
932 free(tempBuf);
933
934 mVendorData = (char *)pFwReq;
935 mDataLen = message_len;
936
937 int ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
938 if (ret < 0) {
939 ALOGE("%s: put_bytes Error:%d",__func__, ret);
940 cleanup();
941 return ret;
942 }
943 hexdump(mVendorData, mDataLen);
944 return ret;
945 }
946
947 //callback handlers registered for nl message send
error_handler_nan(struct sockaddr_nl * nla,struct nlmsgerr * err,void * arg)948 static int error_handler_nan(struct sockaddr_nl *nla, struct nlmsgerr *err,
949 void *arg)
950 {
951 struct sockaddr_nl * tmp;
952 int *ret = (int *)arg;
953 tmp = nla;
954 *ret = err->error;
955 ALOGE("%s: Error code:%d (%s)", __func__, *ret, strerror(-(*ret)));
956 return NL_STOP;
957 }
958
959 //callback handlers registered for nl message send
ack_handler_nan(struct nl_msg * msg,void * arg)960 static int ack_handler_nan(struct nl_msg *msg, void *arg)
961 {
962 int *ret = (int *)arg;
963 struct nl_msg * a;
964
965 ALOGE("%s: called", __func__);
966 a = msg;
967 *ret = 0;
968 return NL_STOP;
969 }
970
971 //callback handlers registered for nl message send
finish_handler_nan(struct nl_msg * msg,void * arg)972 static int finish_handler_nan(struct nl_msg *msg, void *arg)
973 {
974 int *ret = (int *)arg;
975 struct nl_msg * a;
976
977 ALOGE("%s: called", __func__);
978 a = msg;
979 *ret = 0;
980 return NL_SKIP;
981 }
982
983
984 //Override base class requestEvent and implement little differently here
985 //This will send the request message
986 //We dont wait for any response back in case of Nan as it is asynchronous
987 //thus no wait for condition.
requestEvent()988 int NanCommand::requestEvent()
989 {
990 int res;
991 struct nl_cb * cb;
992
993 cb = nl_cb_alloc(NL_CB_DEFAULT);
994 if (!cb) {
995 ALOGE("%s: Callback allocation failed",__func__);
996 res = -1;
997 goto out;
998 }
999
1000 /* send message */
1001 ALOGV("%s:Handle:%p Socket Value:%p", __func__, mInfo, mInfo->cmd_sock);
1002 res = nl_send_auto_complete(mInfo->cmd_sock, mMsg.getMessage());
1003 if (res < 0)
1004 goto out;
1005 res = 1;
1006
1007 nl_cb_err(cb, NL_CB_CUSTOM, error_handler_nan, &res);
1008 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler_nan, &res);
1009 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler_nan, &res);
1010
1011 // err is populated as part of finish_handler
1012 while (res > 0)
1013 nl_recvmsgs(mInfo->cmd_sock, cb);
1014
1015 out:
1016 //free the VendorData
1017 if (mVendorData) {
1018 free(mVendorData);
1019 }
1020 mVendorData = NULL;
1021 //cleanup the mMsg
1022 mMsg.destroy();
1023 return res;
1024 }
1025
calcNanTransmitPostDiscoverySize(const NanTransmitPostDiscovery * pPostDiscovery)1026 int NanCommand::calcNanTransmitPostDiscoverySize(
1027 const NanTransmitPostDiscovery *pPostDiscovery)
1028 {
1029 /* Fixed size of u32 for Conn Type, Device Role and R flag + Dur + Rsvd*/
1030 int ret = sizeof(u32);
1031 /* size of availability interval bit map is 4 bytes */
1032 ret += sizeof(u32);
1033 /* size of mac address is 6 bytes*/
1034 ret += (SIZEOF_TLV_HDR + NAN_MAC_ADDR_LEN);
1035 if (pPostDiscovery &&
1036 pPostDiscovery->type == NAN_CONN_WLAN_MESH) {
1037 /* size of WLAN_MESH_ID */
1038 ret += (SIZEOF_TLV_HDR + \
1039 pPostDiscovery->mesh_id_len);
1040 }
1041 if (pPostDiscovery &&
1042 pPostDiscovery->type == NAN_CONN_WLAN_INFRA) {
1043 /* size of Infrastructure ssid */
1044 ret += (SIZEOF_TLV_HDR + \
1045 pPostDiscovery->infrastructure_ssid_len);
1046 }
1047 ALOGV("%s:size:%d", __func__, ret);
1048 return ret;
1049 }
1050
fillNanSocialChannelParamVal(const NanSocialChannelScanParams * pScanParams,u32 * pChannelParamArr)1051 void NanCommand::fillNanSocialChannelParamVal(
1052 const NanSocialChannelScanParams *pScanParams,
1053 u32* pChannelParamArr)
1054 {
1055 int i;
1056 if (pChannelParamArr) {
1057 memset(pChannelParamArr, 0,
1058 NAN_MAX_SOCIAL_CHANNELS * sizeof(u32));
1059 for (i= 0; i < NAN_MAX_SOCIAL_CHANNELS; i++) {
1060 pChannelParamArr[i] = pScanParams->scan_period[i] << 16;
1061 pChannelParamArr[i] |= pScanParams->dwell_time[i] << 8;
1062 }
1063 pChannelParamArr[NAN_CHANNEL_24G_BAND] |= 6;
1064 pChannelParamArr[NAN_CHANNEL_5G_BAND_LOW]|= 44;
1065 pChannelParamArr[NAN_CHANNEL_5G_BAND_HIGH]|= 149;
1066 ALOGV("%s: Filled SocialChannelParamVal", __func__);
1067 hexdump((char*)pChannelParamArr, NAN_MAX_SOCIAL_CHANNELS * sizeof(u32));
1068 }
1069 return;
1070 }
1071
getNanTransmitPostConnectivityCapabilityVal(const NanTransmitPostConnectivityCapability * pCapab)1072 u32 NanCommand::getNanTransmitPostConnectivityCapabilityVal(
1073 const NanTransmitPostConnectivityCapability *pCapab)
1074 {
1075 u32 ret = 0;
1076 ret |= (pCapab->payload_transmit_flag? 1:0) << 16;
1077 ret |= (pCapab->is_mesh_supported? 1:0) << 5;
1078 ret |= (pCapab->is_ibss_supported? 1:0) << 4;
1079 ret |= (pCapab->wlan_infra_field? 1:0) << 3;
1080 ret |= (pCapab->is_tdls_supported? 1:0) << 2;
1081 ret |= (pCapab->is_wfds_supported? 1:0) << 1;
1082 ret |= (pCapab->is_wfd_supported? 1:0);
1083 ALOGV("%s: val:%d", __func__, ret);
1084 return ret;
1085 }
1086
fillNanTransmitPostDiscoveryVal(const NanTransmitPostDiscovery * pTxDisc,u8 * pOutValue)1087 void NanCommand::fillNanTransmitPostDiscoveryVal(
1088 const NanTransmitPostDiscovery *pTxDisc,
1089 u8 *pOutValue)
1090 {
1091
1092 if (pTxDisc && pOutValue) {
1093 u8 *tlvs = &pOutValue[8];
1094 pOutValue[0] = pTxDisc->type;
1095 pOutValue[1] = pTxDisc->role;
1096 pOutValue[2] = (pTxDisc->transmit_freq? 1:0);
1097 pOutValue[2] |= ((pTxDisc->duration & 0x03) << 1);
1098 memcpy(&pOutValue[4], &pTxDisc->avail_interval_bitmap,
1099 sizeof(pTxDisc->avail_interval_bitmap));
1100 tlvs = addTlv(NAN_TLV_TYPE_MAC_ADDRESS,
1101 NAN_MAC_ADDR_LEN,
1102 (const u8*)&pTxDisc->addr[0],
1103 tlvs);
1104 if (pTxDisc->type == NAN_CONN_WLAN_MESH) {
1105 tlvs = addTlv(NAN_TLV_TYPE_WLAN_MESH_ID,
1106 pTxDisc->mesh_id_len,
1107 (const u8*)&pTxDisc->mesh_id[0],
1108 tlvs);
1109 }
1110 if (pTxDisc->type == NAN_CONN_WLAN_INFRA) {
1111 tlvs = addTlv(NAN_TLV_TYPE_WLAN_INFRA_SSID,
1112 pTxDisc->infrastructure_ssid_len,
1113 (const u8*)&pTxDisc->infrastructure_ssid_val[0],
1114 tlvs);
1115 }
1116 ALOGV("%s: Filled TransmitPostDiscoveryVal", __func__);
1117 hexdump((char*)pOutValue, calcNanTransmitPostDiscoverySize(pTxDisc));
1118 }
1119
1120 return;
1121 }
1122
fillNanFurtherAvailabilityMapVal(const NanFurtherAvailabilityMap * pFam,u8 * pOutValue)1123 void NanCommand::fillNanFurtherAvailabilityMapVal(
1124 const NanFurtherAvailabilityMap *pFam,
1125 u8 *pOutValue)
1126 {
1127 int idx = 0;
1128
1129 if (pFam && pOutValue) {
1130 u32 famsize = calcNanFurtherAvailabilityMapSize(pFam);
1131 pNanFurtherAvailabilityMapAttrTlv pFwReq = \
1132 (pNanFurtherAvailabilityMapAttrTlv)pOutValue;
1133
1134 memset(pOutValue, 0, famsize);
1135 pFwReq->numChan = pFam->numchans;
1136 for (idx = 0; idx < pFam->numchans; idx++) {
1137 const NanFurtherAvailabilityChannel *pFamChan = \
1138 &pFam->famchan[idx];
1139 pNanFurtherAvailabilityChan pFwFamChan = \
1140 (pNanFurtherAvailabilityChan)((u8*)&pFwReq->pFaChan[0] + \
1141 (idx * sizeof(NanFurtherAvailabilityChan)));
1142
1143 pFwFamChan->entryCtrl.availIntDuration = \
1144 pFamChan->entry_control;
1145 pFwFamChan->entryCtrl.mapId = \
1146 pFamChan->mapid;
1147 pFwFamChan->opClass = pFamChan->class_val;
1148 pFwFamChan->channel = pFamChan->channel;
1149 memcpy(&pFwFamChan->availIntBitmap,
1150 &pFamChan->avail_interval_bitmap,
1151 sizeof(pFwFamChan->availIntBitmap));
1152 }
1153 ALOGV("%s: Filled FurtherAvailabilityMapVal", __func__);
1154 hexdump((char*)pOutValue, famsize);
1155 }
1156 return;
1157 }
1158
calcNanFurtherAvailabilityMapSize(const NanFurtherAvailabilityMap * pFam)1159 int NanCommand::calcNanFurtherAvailabilityMapSize(
1160 const NanFurtherAvailabilityMap *pFam)
1161 {
1162 int ret = 0;
1163 if (pFam && pFam->numchans &&
1164 pFam->numchans <= NAN_MAX_FAM_CHANNELS) {
1165 /* Fixed size of u8 for numchans*/
1166 ret = sizeof(u8);
1167 /* numchans * sizeof(FamChannels) */
1168 ret += (pFam->numchans * sizeof(NanFurtherAvailabilityChan));
1169 }
1170 ALOGV("%s:size:%d", __func__, ret);
1171 return ret;
1172 }
1173
putNanCapabilities(transaction_id id)1174 int NanCommand::putNanCapabilities(transaction_id id)
1175 {
1176 size_t message_len = sizeof(NanCapabilitiesReqMsg);
1177
1178 pNanCapabilitiesReqMsg pFwReq = (pNanCapabilitiesReqMsg)malloc(message_len);
1179 if (pFwReq == NULL) {
1180 cleanup();
1181 return WIFI_ERROR_OUT_OF_MEMORY;
1182 }
1183
1184 memset (pFwReq, 0, message_len);
1185 pFwReq->fwHeader.msgVersion = (u16)NAN_MSG_VERSION1;
1186 pFwReq->fwHeader.msgId = NAN_MSG_ID_CAPABILITIES_REQ;
1187 pFwReq->fwHeader.msgLen = message_len;
1188 pFwReq->fwHeader.transactionId = id;
1189
1190 mVendorData = (char*)pFwReq;
1191 mDataLen = message_len;
1192
1193 int ret = mMsg.put_bytes(NL80211_ATTR_VENDOR_DATA, mVendorData, mDataLen);
1194 if (ret < 0) {
1195 ALOGE("%s: put_bytes Error:%d",__func__, ret);
1196 cleanup();
1197 return ret;
1198 }
1199 hexdump(mVendorData, mDataLen);
1200 return ret;
1201 }
1202