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 <errno.h>
20 #include "wifi_hal.h"
21 #include "nan_i.h"
22 #include "nancommand.h"
23 #include "qca-vendor.h"
24 #include <errno.h>
25
26 //Function which calls the necessaryIndication callback
27 //based on the indication type
handleNanIndication()28 int NanCommand::handleNanIndication()
29 {
30 //Based on the message_id in the header determine the Indication type
31 //and call the necessary callback handler
32 u16 msg_id;
33 int res = 0;
34
35 msg_id = getIndicationType();
36
37 ALOGV("handleNanIndication msg_id:%u", msg_id);
38 switch (msg_id) {
39 case NAN_INDICATION_PUBLISH_TERMINATED:
40 NanPublishTerminatedInd publishTerminatedInd;
41 memset(&publishTerminatedInd, 0, sizeof(publishTerminatedInd));
42 res = getNanPublishTerminated(&publishTerminatedInd);
43 if (!res && mHandler.EventPublishTerminated) {
44 (*mHandler.EventPublishTerminated)(&publishTerminatedInd);
45 }
46 break;
47
48 case NAN_INDICATION_MATCH:
49 NanMatchInd matchInd;
50 memset(&matchInd, 0, sizeof(matchInd));
51 res = getNanMatch(&matchInd);
52 if (!res && mHandler.EventMatch) {
53 (*mHandler.EventMatch)(&matchInd);
54 }
55 break;
56
57 case NAN_INDICATION_MATCH_EXPIRED:
58 NanMatchExpiredInd matchExpiredInd;
59 memset(&matchExpiredInd, 0, sizeof(matchExpiredInd));
60 res = getNanMatchExpired(&matchExpiredInd);
61 if (!res && mHandler.EventMatchExpired) {
62 (*mHandler.EventMatchExpired)(&matchExpiredInd);
63 }
64 break;
65
66 case NAN_INDICATION_SUBSCRIBE_TERMINATED:
67 NanSubscribeTerminatedInd subscribeTerminatedInd;
68 memset(&subscribeTerminatedInd, 0, sizeof(subscribeTerminatedInd));
69 res = getNanSubscribeTerminated(&subscribeTerminatedInd);
70 if (!res && mHandler.EventSubscribeTerminated) {
71 (*mHandler.EventSubscribeTerminated)(&subscribeTerminatedInd);
72 }
73 break;
74
75 case NAN_INDICATION_DE_EVENT:
76 NanDiscEngEventInd discEngEventInd;
77 memset(&discEngEventInd, 0, sizeof(discEngEventInd));
78 res = getNanDiscEngEvent(&discEngEventInd);
79 if (!res && mHandler.EventDiscEngEvent) {
80 (*mHandler.EventDiscEngEvent)(&discEngEventInd);
81 }
82 break;
83
84 case NAN_INDICATION_FOLLOWUP:
85 NanFollowupInd followupInd;
86 memset(&followupInd, 0, sizeof(followupInd));
87 res = getNanFollowup(&followupInd);
88 if (!res && mHandler.EventFollowup) {
89 (*mHandler.EventFollowup)(&followupInd);
90 }
91 break;
92
93 case NAN_INDICATION_DISABLED:
94 NanDisabledInd disabledInd;
95 memset(&disabledInd, 0, sizeof(disabledInd));
96 res = getNanDisabled(&disabledInd);
97 if (!res && mHandler.EventDisabled) {
98 (*mHandler.EventDisabled)(&disabledInd);
99 }
100 break;
101
102 case NAN_INDICATION_TCA:
103 NanTCAInd tcaInd;
104 memset(&tcaInd, 0, sizeof(tcaInd));
105 res = getNanTca(&tcaInd);
106 if (!res && mHandler.EventTca) {
107 (*mHandler.EventTca)(&tcaInd);
108 }
109 break;
110
111 case NAN_INDICATION_BEACON_SDF_PAYLOAD:
112 NanBeaconSdfPayloadInd beaconSdfPayloadInd;
113 memset(&beaconSdfPayloadInd, 0, sizeof(beaconSdfPayloadInd));
114 res = getNanBeaconSdfPayload(&beaconSdfPayloadInd);
115 if (!res && mHandler.EventBeaconSdfPayload) {
116 (*mHandler.EventBeaconSdfPayload)(&beaconSdfPayloadInd);
117 }
118 break;
119
120 default:
121 ALOGE("handleNanIndication error invalid msg_id:%u", msg_id);
122 res = (int)WIFI_ERROR_INVALID_REQUEST_ID;
123 break;
124 }
125 return res;
126 }
127
128 //Function which will return the Nan Indication type based on
129 //the initial few bytes of mNanVendorEvent
getIndicationType()130 NanIndicationType NanCommand::getIndicationType()
131 {
132 if (mNanVendorEvent == NULL) {
133 ALOGE("%s: Invalid argument mNanVendorEvent:%p",
134 __func__, mNanVendorEvent);
135 return NAN_INDICATION_UNKNOWN;
136 }
137
138 NanMsgHeader *pHeader = (NanMsgHeader *)mNanVendorEvent;
139
140 switch (pHeader->msgId) {
141 case NAN_MSG_ID_PUBLISH_REPLIED_IND:
142 return NAN_INDICATION_UNKNOWN;
143 case NAN_MSG_ID_PUBLISH_TERMINATED_IND:
144 return NAN_INDICATION_PUBLISH_TERMINATED;
145 case NAN_MSG_ID_MATCH_IND:
146 return NAN_INDICATION_MATCH;
147 case NAN_MSG_ID_MATCH_EXPIRED_IND:
148 return NAN_INDICATION_MATCH_EXPIRED;
149 case NAN_MSG_ID_FOLLOWUP_IND:
150 return NAN_INDICATION_FOLLOWUP;
151 case NAN_MSG_ID_SUBSCRIBE_TERMINATED_IND:
152 return NAN_INDICATION_SUBSCRIBE_TERMINATED;
153 case NAN_MSG_ID_DE_EVENT_IND:
154 return NAN_INDICATION_DE_EVENT;
155 case NAN_MSG_ID_DISABLE_IND:
156 return NAN_INDICATION_DISABLED;
157 case NAN_MSG_ID_TCA_IND:
158 return NAN_INDICATION_TCA;
159 case NAN_MSG_ID_BEACON_SDF_IND:
160 return NAN_INDICATION_BEACON_SDF_PAYLOAD;
161 default:
162 return NAN_INDICATION_UNKNOWN;
163 }
164 }
165
getNanPublishTerminated(NanPublishTerminatedInd * event)166 int NanCommand::getNanPublishTerminated(NanPublishTerminatedInd *event)
167 {
168 if (event == NULL || mNanVendorEvent == NULL) {
169 ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
170 __func__, event, mNanVendorEvent);
171 return WIFI_ERROR_INVALID_ARGS;
172 }
173
174 pNanPublishTerminatedIndMsg pRsp = (pNanPublishTerminatedIndMsg)mNanVendorEvent;
175 event->publish_id = pRsp->fwHeader.handle;
176 event->reason = (NanStatusType)pRsp->reason;
177 return WIFI_SUCCESS;
178 }
179
getNanMatch(NanMatchInd * event)180 int NanCommand::getNanMatch(NanMatchInd *event)
181 {
182 if (event == NULL || mNanVendorEvent == NULL) {
183 ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
184 __func__, event, mNanVendorEvent);
185 return WIFI_ERROR_INVALID_ARGS;
186 }
187
188 pNanMatchIndMsg pRsp = (pNanMatchIndMsg)mNanVendorEvent;
189 event->publish_subscribe_id = pRsp->fwHeader.handle;
190 event->requestor_instance_id = pRsp->matchIndParams.matchHandle;
191 event->match_occured_flag = pRsp->matchIndParams.matchOccuredFlag;
192 event->out_of_resource_flag = pRsp->matchIndParams.outOfResourceFlag;
193
194 u8 *pInputTlv = pRsp->ptlv;
195 NanTlv outputTlv;
196 u16 readLen = 0;
197 int remainingLen = (mNanDataLen - \
198 (sizeof(NanMsgHeader) + sizeof(NanMatchIndParams)));
199 int ret = 0, idx = 0;
200
201 //Has SDF match filter and service specific info TLV
202 if (remainingLen <= 0) {
203 ALOGV("%s: No TLV's present",__func__);
204 return WIFI_SUCCESS;
205 }
206 ALOGV("%s: TLV remaining Len:%d",__func__, remainingLen);
207 while ((remainingLen > 0) &&
208 (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
209 ALOGV("%s: Remaining Len:%d readLen:%d type:%d length:%d",
210 __func__, remainingLen, readLen, outputTlv.type,
211 outputTlv.length);
212 switch (outputTlv.type) {
213 case NAN_TLV_TYPE_SERVICE_SPECIFIC_INFO:
214 if (outputTlv.length > NAN_MAX_SERVICE_NAME_LEN) {
215 outputTlv.length = NAN_MAX_SERVICE_NAME_LEN;
216 }
217 event->service_specific_info_len = outputTlv.length;
218 memcpy(event->service_specific_info, outputTlv.value,
219 outputTlv.length);
220 break;
221 case NAN_TLV_TYPE_SDF_MATCH_FILTER:
222 if (outputTlv.length > NAN_MAX_MATCH_FILTER_LEN) {
223 outputTlv.length = NAN_MAX_MATCH_FILTER_LEN;
224 }
225 event->sdf_match_filter_len = outputTlv.length;
226 memcpy(event->sdf_match_filter, outputTlv.value,
227 outputTlv.length);
228 break;
229 case NAN_TLV_TYPE_MAC_ADDRESS:
230 if (outputTlv.length > sizeof(event->addr)) {
231 outputTlv.length = sizeof(event->addr);
232 }
233 memcpy(event->addr, outputTlv.value, outputTlv.length);
234 break;
235 case NAN_TLV_TYPE_RECEIVED_RSSI_VALUE:
236 if (outputTlv.length > sizeof(event->rssi_value)) {
237 outputTlv.length = sizeof(event->rssi_value);
238 }
239 memcpy(&event->rssi_value, outputTlv.value,
240 outputTlv.length);
241 break;
242 case NAN_TLV_TYPE_POST_NAN_CONNECTIVITY_CAPABILITIES_RECEIVE:
243 if (outputTlv.length != sizeof(u32)) {
244 ALOGE("NAN_TLV_TYPE_POST_NAN_CONNECTIVITY_CAPABILITIES_RECEIVE"
245 "Incorrect size:%d expecting %zu", outputTlv.length,
246 sizeof(u32));
247 break;
248 }
249 event->is_conn_capability_valid = 1;
250 /* Populate conn_capability from received TLV */
251 getNanReceivePostConnectivityCapabilityVal(outputTlv.value,
252 &event->conn_capability);
253 break;
254 case NAN_TLV_TYPE_POST_NAN_DISCOVERY_ATTRIBUTE_RECEIVE:
255 /* Populate receive discovery attribute from
256 received TLV */
257 idx = event->num_rx_discovery_attr;
258 ret = getNanReceivePostDiscoveryVal(outputTlv.value,
259 outputTlv.length,
260 &event->discovery_attr[idx]);
261 if (ret == 0) {
262 event->num_rx_discovery_attr++;
263 }
264 else {
265 ALOGE("NAN_TLV_TYPE_POST_NAN_DISCOVERY_ATTRIBUTE_RECEIVE"
266 "Incorrect");
267 }
268 break;
269 case NAN_TLV_TYPE_FURTHER_AVAILABILITY_MAP:
270 /* Populate further availability bitmap from
271 received TLV */
272 ret = getNanFurtherAvailabilityMap(outputTlv.value,
273 outputTlv.length,
274 &event->num_chans,
275 &event->famchan[0]);
276 if (ret < 0)
277 ALOGE("NAN_TLV_TYPE_FURTHER_AVAILABILITY_MAP"
278 "Incorrect");
279 break;
280 case NAN_TLV_TYPE_CLUSTER_ATTRIBUTE:
281 if (outputTlv.length > sizeof(event->cluster_attribute)) {
282 outputTlv.length = sizeof(event->cluster_attribute);
283 }
284 memcpy(event->cluster_attribute,
285 outputTlv.value, outputTlv.length);
286 event->cluster_attribute_len = outputTlv.length;
287 break;
288 default:
289 ALOGV("Unknown TLV type skipped");
290 break;
291 }
292 remainingLen -= readLen;
293 pInputTlv += readLen;
294 memset(&outputTlv, 0, sizeof(outputTlv));
295 }
296 return WIFI_SUCCESS;
297 }
298
getNanMatchExpired(NanMatchExpiredInd * event)299 int NanCommand::getNanMatchExpired(NanMatchExpiredInd *event)
300 {
301 if (event == NULL || mNanVendorEvent == NULL) {
302 ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
303 __func__, event, mNanVendorEvent);
304 return WIFI_ERROR_INVALID_ARGS;
305 }
306
307 pNanMatchExpiredIndMsg pRsp = (pNanMatchExpiredIndMsg)mNanVendorEvent;
308 event->publish_subscribe_id = pRsp->fwHeader.handle;
309 event->requestor_instance_id = pRsp->matchExpiredIndParams.matchHandle;
310 return WIFI_SUCCESS;
311 }
312
getNanSubscribeTerminated(NanSubscribeTerminatedInd * event)313 int NanCommand::getNanSubscribeTerminated(NanSubscribeTerminatedInd *event)
314 {
315 if (event == NULL || mNanVendorEvent == NULL) {
316 ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
317 __func__, event, mNanVendorEvent);
318 return WIFI_ERROR_INVALID_ARGS;
319 }
320
321 pNanSubscribeTerminatedIndMsg pRsp = (pNanSubscribeTerminatedIndMsg)mNanVendorEvent;
322 event->subscribe_id = pRsp->fwHeader.handle;
323 event->reason = (NanStatusType)pRsp->reason;
324 return WIFI_SUCCESS;
325 }
326
getNanFollowup(NanFollowupInd * event)327 int NanCommand::getNanFollowup(NanFollowupInd *event)
328 {
329 if (event == NULL || mNanVendorEvent == NULL) {
330 ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
331 __func__, event, mNanVendorEvent);
332 return WIFI_ERROR_INVALID_ARGS;
333 }
334
335 pNanFollowupIndMsg pRsp = (pNanFollowupIndMsg)mNanVendorEvent;
336 event->publish_subscribe_id = pRsp->fwHeader.handle;
337 event->requestor_instance_id = pRsp->followupIndParams.matchHandle;
338 event->dw_or_faw = pRsp->followupIndParams.window;
339
340 u8 *pInputTlv = pRsp->ptlv;
341 NanTlv outputTlv;
342 u16 readLen = 0;
343 int remainingLen = (mNanDataLen - \
344 (sizeof(NanMsgHeader) + sizeof(NanFollowupIndParams)));
345
346 //Has service specific info and extended service specific info TLV
347 if (remainingLen <= 0) {
348 ALOGV("%s: No TLV's present",__func__);
349 return WIFI_SUCCESS;
350 }
351 ALOGV("%s: TLV remaining Len:%d",__func__, remainingLen);
352 while ((remainingLen > 0) &&
353 (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
354 ALOGV("%s: Remaining Len:%d readLen:%d type:%d length:%d",
355 __func__, remainingLen, readLen, outputTlv.type,
356 outputTlv.length);
357 switch (outputTlv.type) {
358 case NAN_TLV_TYPE_SERVICE_SPECIFIC_INFO:
359 case NAN_TLV_TYPE_EXT_SERVICE_SPECIFIC_INFO:
360 if (outputTlv.length > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) {
361 outputTlv.length = NAN_MAX_SERVICE_SPECIFIC_INFO_LEN;
362 }
363 event->service_specific_info_len = outputTlv.length;
364 memcpy(event->service_specific_info, outputTlv.value,
365 outputTlv.length);
366 break;
367 case NAN_TLV_TYPE_MAC_ADDRESS:
368 if (outputTlv.length > sizeof(event->addr)) {
369 outputTlv.length = sizeof(event->addr);
370 }
371 memcpy(event->addr, outputTlv.value, outputTlv.length);
372 break;
373 default:
374 ALOGV("Unknown TLV type skipped");
375 break;
376 }
377 remainingLen -= readLen;
378 pInputTlv += readLen;
379 memset(&outputTlv, 0, sizeof(outputTlv));
380 }
381 return WIFI_SUCCESS;
382 }
383
getNanDiscEngEvent(NanDiscEngEventInd * event)384 int NanCommand::getNanDiscEngEvent(NanDiscEngEventInd *event)
385 {
386 if (event == NULL || mNanVendorEvent == NULL) {
387 ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
388 __func__, event, mNanVendorEvent);
389 return WIFI_ERROR_INVALID_ARGS;
390 }
391
392 pNanEventIndMsg pRsp = (pNanEventIndMsg)mNanVendorEvent;
393 memset(&event->data, 0, sizeof(event->data));
394
395 u8 *pInputTlv = pRsp->ptlv;
396 NanTlv outputTlv;
397 u16 readLen = 0;
398 int remainingLen = (mNanDataLen - \
399 (sizeof(NanMsgHeader)));
400
401 //Has Self-STA Mac TLV
402 if (remainingLen <= 0) {
403 ALOGE("%s: No TLV's present",__func__);
404 return WIFI_SUCCESS;
405 }
406
407 ALOGV("%s: TLV remaining Len:%d",__func__, remainingLen);
408 while ((remainingLen > 0) &&
409 (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
410 ALOGV("%s: Remaining Len:%d readLen:%d type:%d length:%d",
411 __func__, remainingLen, readLen, outputTlv.type,
412 outputTlv.length);
413 switch (outputTlv.type) {
414 case NAN_TLV_TYPE_EVENT_SELF_STATION_MAC_ADDRESS:
415 if (outputTlv.length > NAN_MAC_ADDR_LEN) {
416 ALOGV("%s: Reading only first %d bytes of TLV",
417 __func__, NAN_MAC_ADDR_LEN);
418 outputTlv.length = NAN_MAC_ADDR_LEN;
419 }
420 memcpy(event->data.mac_addr.addr, outputTlv.value,
421 outputTlv.length);
422 event->event_type = NAN_EVENT_ID_DISC_MAC_ADDR;
423 break;
424 case NAN_TLV_TYPE_EVENT_STARTED_CLUSTER:
425 if (outputTlv.length > NAN_MAC_ADDR_LEN) {
426 ALOGV("%s: Reading only first %d bytes of TLV",
427 __func__, NAN_MAC_ADDR_LEN);
428 outputTlv.length = NAN_MAC_ADDR_LEN;
429 }
430 memcpy(event->data.cluster.addr, outputTlv.value,
431 outputTlv.length);
432 event->event_type = NAN_EVENT_ID_STARTED_CLUSTER;
433 break;
434 case NAN_TLV_TYPE_EVENT_JOINED_CLUSTER:
435 if (outputTlv.length > NAN_MAC_ADDR_LEN) {
436 ALOGV("%s: Reading only first %d bytes of TLV",
437 __func__, NAN_MAC_ADDR_LEN);
438 outputTlv.length = NAN_MAC_ADDR_LEN;
439 }
440 memcpy(event->data.cluster.addr, outputTlv.value,
441 outputTlv.length);
442 event->event_type = NAN_EVENT_ID_JOINED_CLUSTER;
443 break;
444 default:
445 ALOGV("Unhandled TLV type:%d", outputTlv.type);
446 break;
447 }
448 remainingLen -= readLen;
449 pInputTlv += readLen;
450 memset(&outputTlv,0, sizeof(outputTlv));
451 }
452 return WIFI_SUCCESS;
453 }
454
getNanDisabled(NanDisabledInd * event)455 int NanCommand::getNanDisabled(NanDisabledInd *event)
456 {
457 if (event == NULL || mNanVendorEvent == NULL) {
458 ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
459 __func__, event, mNanVendorEvent);
460 return WIFI_ERROR_INVALID_ARGS;
461 }
462
463 pNanDisableIndMsg pRsp = (pNanDisableIndMsg)mNanVendorEvent;
464 event->reason = (NanStatusType)pRsp->reason;
465 return WIFI_SUCCESS;
466
467 }
468
getNanTca(NanTCAInd * event)469 int NanCommand::getNanTca(NanTCAInd *event)
470 {
471 if (event == NULL || mNanVendorEvent == NULL) {
472 ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
473 __func__, event, mNanVendorEvent);
474 return WIFI_ERROR_INVALID_ARGS;
475 }
476
477 pNanTcaIndMsg pRsp = (pNanTcaIndMsg)mNanVendorEvent;
478 memset(&event->data, 0, sizeof(event->data));
479
480 u8 *pInputTlv = pRsp->ptlv;
481 NanTlv outputTlv;
482 u16 readLen = 0;
483
484 int remainingLen = (mNanDataLen - \
485 (sizeof(NanMsgHeader)));
486
487 //Has NAN_TCA_ID_CLUSTER_SIZE
488 if (remainingLen <= 0) {
489 ALOGE("%s: No TLV's present",__func__);
490 return WIFI_SUCCESS;
491 }
492
493 ALOGV("%s: TLV remaining Len:%d",__func__, remainingLen);
494 while ((remainingLen > 0) &&
495 (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
496 ALOGV("%s: Remaining Len:%d readLen:%d type:%d length:%d",
497 __func__, remainingLen, readLen, outputTlv.type,
498 outputTlv.length);
499 switch (outputTlv.type) {
500 case NAN_TLV_TYPE_CLUSTER_SIZE_RSP:
501 if (outputTlv.length != 2 * sizeof(u32)) {
502 ALOGE("%s: Wrong length %d in Tca Indication expecting %zu bytes",
503 __func__, outputTlv.length, 2 * sizeof(u32));
504 break;
505 }
506 event->rising_direction_evt_flag = outputTlv.value[0] & 0x01;
507 event->falling_direction_evt_flag = (outputTlv.value[0] & 0x02) >> 1;
508 memcpy(&(event->data.cluster.cluster_size), &outputTlv.value[4],
509 sizeof(event->data.cluster.cluster_size));
510 event->tca_type = NAN_TCA_ID_CLUSTER_SIZE;
511 break;
512 default:
513 ALOGV("Unhandled TLV type:%d", outputTlv.type);
514 break;
515 }
516 remainingLen -= readLen;
517 pInputTlv += readLen;
518 memset(&outputTlv,0, sizeof(outputTlv));
519 }
520 return WIFI_SUCCESS;
521 }
522
getNanBeaconSdfPayload(NanBeaconSdfPayloadInd * event)523 int NanCommand::getNanBeaconSdfPayload(NanBeaconSdfPayloadInd *event)
524 {
525 if (event == NULL || mNanVendorEvent == NULL) {
526 ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
527 __func__, event, mNanVendorEvent);
528 return WIFI_ERROR_INVALID_ARGS;
529 }
530
531 pNanBeaconSdfPayloadIndMsg pRsp = (pNanBeaconSdfPayloadIndMsg)mNanVendorEvent;
532 memset(&event->data, 0, sizeof(event->data));
533
534 u8 *pInputTlv = pRsp->ptlv;
535 NanTlv outputTlv;
536 u16 readLen = 0;
537 int remainingLen = (mNanDataLen - \
538 (sizeof(NanMsgHeader)));
539
540 //Has Mac address
541 if (remainingLen <= 0) {
542 ALOGV("%s: No TLV's present",__func__);
543 return WIFI_SUCCESS;
544 }
545
546 ALOGV("%s: TLV remaining Len:%d",__func__, remainingLen);
547 while ((remainingLen > 0) &&
548 (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
549 ALOGV("%s: Remaining Len:%d readLen:%d type:%d length:%d",
550 __func__, remainingLen, readLen, outputTlv.type,
551 outputTlv.length);
552 switch (outputTlv.type) {
553 case NAN_TLV_TYPE_MAC_ADDRESS:
554 if (outputTlv.length > sizeof(event->addr)) {
555 outputTlv.length = sizeof(event->addr);
556 }
557 memcpy(event->addr, outputTlv.value,
558 outputTlv.length);
559 break;
560
561 case NAN_TLV_TYPE_VENDOR_SPECIFIC_ATTRIBUTE_RECEIVE:
562 {
563 NanReceiveVendorSpecificAttribute* recvVsaattr = &event->vsa;
564 if (outputTlv.length < sizeof(u32)) {
565 ALOGE("NAN_TLV_TYPE_VENDOR_SPECIFIC_ATTRIBUTE_RECEIVE"
566 "Incorrect length:%d", outputTlv.length);
567 break;
568 }
569 event->is_vsa_received = 1;
570 recvVsaattr->vsa_received_on = (outputTlv.value[0] >> 1) & 0x07;
571 memcpy(&recvVsaattr->vendor_oui, &outputTlv.value[1],
572 3);
573 recvVsaattr->attr_len = outputTlv.length - 4;
574 if (recvVsaattr->attr_len > NAN_MAX_VSA_DATA_LEN) {
575 recvVsaattr->attr_len = NAN_MAX_VSA_DATA_LEN;
576 }
577 if (recvVsaattr->attr_len) {
578 memcpy(recvVsaattr->vsa, &outputTlv.value[4],
579 recvVsaattr->attr_len);
580 }
581 break;
582 }
583
584 case NAN_TLV_TYPE_BEACON_SDF_PAYLOAD_RECEIVE:
585 event->is_beacon_sdf_payload_received = 1;
586 event->data.frame_len = outputTlv.length;
587 if (event->data.frame_len > NAN_MAX_FRAME_DATA_LEN) {
588 event->data.frame_len = NAN_MAX_FRAME_DATA_LEN;
589 }
590 memcpy(&event->data.frame_data, &outputTlv.value[0],
591 event->data.frame_len);
592 break;
593
594 default:
595 ALOGV("Unhandled TLV Type:%d", outputTlv.type);
596 break;
597 }
598 remainingLen -= readLen;
599 pInputTlv += readLen;
600 memset(&outputTlv,0, sizeof(outputTlv));
601 }
602 return WIFI_SUCCESS;
603 }
604
getNanReceivePostConnectivityCapabilityVal(const u8 * pInValue,NanReceivePostConnectivityCapability * pRxCapab)605 void NanCommand::getNanReceivePostConnectivityCapabilityVal(
606 const u8 *pInValue,
607 NanReceivePostConnectivityCapability *pRxCapab)
608 {
609 if (pInValue && pRxCapab) {
610 pRxCapab->is_mesh_supported = (pInValue[0] & (0x01 << 5));
611 pRxCapab->is_ibss_supported = (pInValue[0] & (0x01 << 4));
612 pRxCapab->wlan_infra_field = (pInValue[0] & (0x01 << 3));
613 pRxCapab->is_tdls_supported = (pInValue[0] & (0x01 << 2));
614 pRxCapab->is_wfds_supported = (pInValue[0] & (0x01 << 1));
615 pRxCapab->is_wfd_supported = pInValue[0] & 0x01;
616 }
617 }
618
getNanReceivePostDiscoveryVal(const u8 * pInValue,u32 length,NanReceivePostDiscovery * pRxDisc)619 int NanCommand::getNanReceivePostDiscoveryVal(const u8 *pInValue,
620 u32 length,
621 NanReceivePostDiscovery *pRxDisc)
622 {
623 int ret = 0;
624
625 if (length <= 8 || pInValue == NULL) {
626 ALOGE("%s: Invalid Arg TLV Len %d < 4",
627 __func__, length);
628 return -1;
629 }
630
631 pRxDisc->type = (NanConnectionType) pInValue[0];
632 pRxDisc->role = (NanDeviceRole) pInValue[1];
633 pRxDisc->duration = (NanAvailDuration) (pInValue[2] & 0x03);
634 pRxDisc->mapid = ((pInValue[2] >> 2) & 0x0F);
635 memcpy(&pRxDisc->avail_interval_bitmap,
636 &pInValue[4],
637 sizeof(pRxDisc->avail_interval_bitmap));
638
639 u8 *pInputTlv = (u8 *)&pInValue[8];
640 NanTlv outputTlv;
641 u16 readLen = 0;
642 int remainingLen = (length - 8);
643
644 //Has Mac address
645 if (remainingLen <= 0) {
646 ALOGE("%s: No TLV's present",__func__);
647 return -1;
648 }
649
650 ALOGV("%s: TLV remaining Len:%d",__func__, remainingLen);
651 while ((remainingLen > 0) &&
652 (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
653 ALOGV("%s: Remaining Len:%d readLen:%d type:%d length:%d",
654 __func__, remainingLen, readLen, outputTlv.type,
655 outputTlv.length);
656 switch (outputTlv.type) {
657 case NAN_TLV_TYPE_MAC_ADDRESS:
658 if (outputTlv.length > sizeof(pRxDisc->addr)) {
659 outputTlv.length = sizeof(pRxDisc->addr);
660 }
661 memcpy(pRxDisc->addr, outputTlv.value, outputTlv.length);
662 break;
663 case NAN_TLV_TYPE_WLAN_MESH_ID:
664 if (outputTlv.length > sizeof(pRxDisc->mesh_id)) {
665 outputTlv.length = sizeof(pRxDisc->mesh_id);
666 }
667 memcpy(pRxDisc->mesh_id, outputTlv.value, outputTlv.length);
668 pRxDisc->mesh_id_len = outputTlv.length;
669 break;
670 case NAN_TLV_TYPE_WLAN_INFRA_SSID:
671 if (outputTlv.length > sizeof(pRxDisc->infrastructure_ssid_val)) {
672 outputTlv.length = sizeof(pRxDisc->infrastructure_ssid_val);
673 }
674 memcpy(pRxDisc->infrastructure_ssid_val, outputTlv.value,
675 outputTlv.length);
676 pRxDisc->infrastructure_ssid_len = outputTlv.length;
677 default:
678 ALOGV("Unhandled TLV Type:%d", outputTlv.type);
679 break;
680 }
681 remainingLen -= readLen;
682 pInputTlv += readLen;
683 memset(&outputTlv,0, sizeof(outputTlv));
684 }
685 return ret;
686 }
687
getNanFurtherAvailabilityMap(const u8 * pInValue,u32 length,u8 * num_chans,NanFurtherAvailabilityChannel * pFac)688 int NanCommand::getNanFurtherAvailabilityMap(const u8 *pInValue,
689 u32 length,
690 u8 *num_chans,
691 NanFurtherAvailabilityChannel *pFac)
692 {
693 int idx = 0;
694
695 if ((length == 0) || pInValue == NULL) {
696 ALOGE("%s: Invalid Arg TLV Len %d or pInValue NULL",
697 __func__, length);
698 return -1;
699 }
700
701 *num_chans = pInValue[0];
702 if (*num_chans > NAN_MAX_FAM_CHANNELS) {
703 ALOGE("%s: Unable to accommodate numchans %d",
704 __func__, *num_chans);
705 return -1;
706 }
707
708 if (length < (sizeof(u8) +
709 (*num_chans * sizeof(NanFurtherAvailabilityChan)))) {
710 ALOGE("%s: Invalid TLV Length", __func__);
711 return -1;
712 }
713
714 for (idx = 0; idx < *num_chans; idx++) {
715 pNanFurtherAvailabilityChan pRsp = \
716 (pNanFurtherAvailabilityChan)((u8 *)&pInValue[1] + \
717 (idx * sizeof(NanFurtherAvailabilityChan)));
718
719 pFac->entry_control = \
720 (NanAvailDuration)(pRsp->entryCtrl.availIntDuration);
721 pFac->mapid = pRsp->entryCtrl.mapId;
722 pFac->class_val = pRsp->opClass;
723 pFac->channel = pRsp->channel;
724 memcpy(&pFac->avail_interval_bitmap,
725 &pRsp->availIntBitmap,
726 sizeof(pFac->avail_interval_bitmap));
727 pFac++;
728 }
729 return 0;
730 }
731
getNanStaParameter(wifi_interface_handle iface,NanStaParameter * pRsp)732 int NanCommand::getNanStaParameter(wifi_interface_handle iface,
733 NanStaParameter *pRsp)
734 {
735 int ret = WIFI_ERROR_NONE;
736 int res = -1;
737 int id = 1;
738 NanCommand *nanCommand = NULL;
739 interface_info *ifaceInfo = getIfaceInfo(iface);
740 wifi_handle wifiHandle = getWifiHandle(iface);
741
742 nanCommand = NanCommand::instance(wifiHandle);
743 if (nanCommand == NULL) {
744 ALOGE("%s: Error NanCommand NULL", __func__);
745 return WIFI_ERROR_UNKNOWN;
746 }
747
748 ret = nanCommand->create();
749 if (ret < 0)
750 goto cleanup;
751
752 /* Set the interface Id of the message. */
753 ret = nanCommand->set_iface_id(ifaceInfo->name);
754 if (ret < 0)
755 goto cleanup;
756
757 /*
758 Construct NL message to get the sync stats parameter
759 which has all the parameter required by staparameter.
760 */
761 NanStatsRequest syncStats;
762 memset(&syncStats, 0, sizeof(syncStats));
763 syncStats.stats_type = NAN_STATS_ID_DE_TIMING_SYNC;
764 syncStats.clear = 0;
765
766 mStaParam = pRsp;
767 ret = putNanStats(id, &syncStats);
768 if (ret != 0) {
769 ALOGE("%s: putNanStats Error:%d",__func__, ret);
770 goto cleanup;
771 }
772 ret = requestEvent();
773 if (ret != 0) {
774 ALOGE("%s: requestEvent Error:%d",__func__, ret);
775 goto cleanup;
776 }
777
778 struct timespec abstime;
779 abstime.tv_sec = 4;
780 abstime.tv_nsec = 0;
781 res = mCondition.wait(abstime);
782 if (res == ETIMEDOUT)
783 {
784 ALOGE("%s: Time out happened.", __func__);
785 ret = WIFI_ERROR_TIMED_OUT;
786 goto cleanup;
787 }
788 ALOGV("%s: NanStaparameter Master_pref:%x," \
789 " Random_factor:%x, hop_count:%x " \
790 " beacon_transmit_time:%d", __func__,
791 pRsp->master_pref, pRsp->random_factor,
792 pRsp->hop_count, pRsp->beacon_transmit_time);
793 cleanup:
794 mStaParam = NULL;
795 return (int)ret;
796 }
797