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 "nan.h"
21 #include "wifi_hal.h"
22 #include "nan_i.h"
23 #include "nancommand.h"
24 #include <errno.h>
25
26 #define NAN_TERMINATED_BEGINNING_OFFSET 8192
27
28 //Function which calls the necessaryIndication callback
29 //based on the indication type
handleNanIndication()30 int NanCommand::handleNanIndication()
31 {
32 //Based on the message_id in the header determine the Indication type
33 //and call the necessary callback handler
34 u16 msg_id;
35 int res = 0;
36
37 ALOGI("handleNanIndication called %p", this);
38 msg_id = getIndicationType();
39
40 ALOGI("handleNanIndication msg_id:%u", msg_id);
41 switch (msg_id) {
42 case NAN_INDICATION_PUBLISH_REPLIED:
43 NanPublishRepliedInd publishRepliedInd;
44 memset(&publishRepliedInd, 0, sizeof(publishRepliedInd));
45 res = getNanPublishReplied(&publishRepliedInd);
46 if (!res && mHandler.EventPublishReplied) {
47 (*mHandler.EventPublishReplied)(&publishRepliedInd,
48 mUserData);
49 }
50 break;
51
52 case NAN_INDICATION_PUBLISH_TERMINATED:
53 NanPublishTerminatedInd publishTerminatedInd;
54 memset(&publishTerminatedInd, 0, sizeof(publishTerminatedInd));
55 res = getNanPublishTerminated(&publishTerminatedInd);
56 if (!res && mHandler.EventPublishTerminated) {
57 (*mHandler.EventPublishTerminated)(&publishTerminatedInd,
58 mUserData);
59 }
60 break;
61
62 case NAN_INDICATION_MATCH:
63 NanMatchInd matchInd;
64 memset(&matchInd, 0, sizeof(matchInd));
65 res = getNanMatch(&matchInd);
66 if (!res && mHandler.EventMatch) {
67 (*mHandler.EventMatch)(&matchInd, mUserData);
68 }
69 break;
70
71 case NAN_INDICATION_UNMATCH:
72 NanUnmatchInd unMatchInd;
73 memset(&unMatchInd, 0, sizeof(unMatchInd));
74 res = getNanUnMatch(&unMatchInd);
75 if (!res && mHandler.EventUnMatch) {
76 (*mHandler.EventUnMatch)(&unMatchInd, mUserData);
77 }
78 break;
79
80 case NAN_INDICATION_SUBSCRIBE_TERMINATED:
81 NanSubscribeTerminatedInd subscribeTerminatedInd;
82 memset(&subscribeTerminatedInd, 0, sizeof(subscribeTerminatedInd));
83 res = getNanSubscribeTerminated(&subscribeTerminatedInd);
84 if (!res && mHandler.EventSubscribeTerminated) {
85 (*mHandler.EventSubscribeTerminated)(&subscribeTerminatedInd,
86 mUserData);
87 }
88 break;
89
90 case NAN_INDICATION_DE_EVENT:
91 NanDiscEngEventInd discEngEventInd;
92 memset(&discEngEventInd, 0, sizeof(discEngEventInd));
93 res = getNanDiscEngEvent(&discEngEventInd);
94 if (!res && mHandler.EventDiscEngEvent) {
95 (*mHandler.EventDiscEngEvent)(&discEngEventInd,
96 mUserData);
97 }
98 break;
99
100 case NAN_INDICATION_FOLLOWUP:
101 NanFollowupInd followupInd;
102 memset(&followupInd, 0, sizeof(followupInd));
103 res = getNanFollowup(&followupInd);
104 if (!res && mHandler.EventFollowup) {
105 (*mHandler.EventFollowup)(&followupInd,
106 mUserData);
107 }
108 break;
109
110 case NAN_INDICATION_DISABLED:
111 NanDisabledInd disabledInd;
112 memset(&disabledInd, 0, sizeof(disabledInd));
113 res = getNanDisabled(&disabledInd);
114 if (!res && mHandler.EventDisabled) {
115 (*mHandler.EventDisabled)(&disabledInd,
116 mUserData);
117 }
118 break;
119
120 case NAN_INDICATION_TCA:
121 NanTCAInd tcaInd;
122 memset(&tcaInd, 0, sizeof(tcaInd));
123 res = getNanTca(&tcaInd);
124 if (!res && mHandler.EventTca) {
125 (*mHandler.EventTca)(&tcaInd,
126 mUserData);
127 }
128 break;
129
130 case NAN_INDICATION_BEACON_SDF_PAYLOAD:
131 NanBeaconSdfPayloadInd beaconSdfPayloadInd;
132 memset(&beaconSdfPayloadInd, 0, sizeof(beaconSdfPayloadInd));
133 res = getNanBeaconSdfPayload(&beaconSdfPayloadInd);
134 if (!res && mHandler.EventSdfPayload) {
135 (*mHandler.EventSdfPayload)(&beaconSdfPayloadInd,
136 mUserData);
137 }
138 break;
139
140 default:
141 ALOGE("handleNanIndication error invalid msg_id:%u", msg_id);
142 res = (int)WIFI_ERROR_INVALID_REQUEST_ID;
143 break;
144 }
145 return res;
146 }
147
148 //Function which will return the Nan Indication type based on
149 //the initial few bytes of mNanVendorEvent
getIndicationType()150 NanIndicationType NanCommand::getIndicationType()
151 {
152 if (mNanVendorEvent == NULL) {
153 ALOGE("%s: Invalid argument mNanVendorEvent:%p",
154 __func__, mNanVendorEvent);
155 return NAN_INDICATION_UNKNOWN;
156 }
157
158 NanMsgHeader *pHeader = (NanMsgHeader *)mNanVendorEvent;
159
160 switch (pHeader->msgId) {
161 case NAN_MSG_ID_PUBLISH_REPLIED_IND:
162 return NAN_INDICATION_PUBLISH_REPLIED;
163 case NAN_MSG_ID_PUBLISH_TERMINATED_IND:
164 return NAN_INDICATION_PUBLISH_TERMINATED;
165 case NAN_MSG_ID_MATCH_IND:
166 return NAN_INDICATION_MATCH;
167 case NAN_MSG_ID_UNMATCH_IND:
168 return NAN_INDICATION_UNMATCH;
169 case NAN_MSG_ID_FOLLOWUP_IND:
170 return NAN_INDICATION_FOLLOWUP;
171 case NAN_MSG_ID_SUBSCRIBE_TERMINATED_IND:
172 return NAN_INDICATION_SUBSCRIBE_TERMINATED;
173 case NAN_MSG_ID_DE_EVENT_IND:
174 return NAN_INDICATION_DE_EVENT;
175 case NAN_MSG_ID_DISABLE_IND:
176 return NAN_INDICATION_DISABLED;
177 case NAN_MSG_ID_TCA_IND:
178 return NAN_INDICATION_TCA;
179 #ifdef NAN_2_0
180 case NAN_MSG_ID_BEACON_SDF_IND:
181 return NAN_INDICATION_BEACON_SDF_PAYLOAD;
182 #endif /* NAN_2_0 */
183 default:
184 return NAN_INDICATION_UNKNOWN;
185 }
186 }
187
getNanPublishReplied(NanPublishRepliedInd * event)188 int NanCommand::getNanPublishReplied(NanPublishRepliedInd *event)
189 {
190 if (event == NULL || mNanVendorEvent == NULL) {
191 ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
192 __func__, event, mNanVendorEvent);
193 return WIFI_ERROR_INVALID_ARGS;
194 }
195
196 pNanPublishRepliedIndMsg pRsp = (pNanPublishRepliedIndMsg)mNanVendorEvent;
197 event->header.handle = pRsp->fwHeader.handle;
198 event->header.transaction_id = pRsp->fwHeader.transactionId;
199 #ifndef NAN_2_0
200 memcpy(event->addr, pRsp->publishRepliedIndParams.macAddr, sizeof(event->addr));
201 #else /* NAN_2_0 */
202 event->rssi_value = 0;
203 u8 *pInputTlv = pRsp->ptlv;
204 NanTlv outputTlv;
205 u16 readLen = 0;
206 int ret = 0;
207 int remainingLen = (mNanDataLen - \
208 (sizeof(NanMsgHeader)));
209
210 //Has NAN Mac address mandatory, received RSSI value optional
211 //POST_NAN_CONNECTIVITY_CAPABILITIES_RECEIVE
212 //POST_NAN_DISCOVERY_ATTRIBUTE_RECEIVE
213 //NAN_FURTHER_AVAILABILITY_MAP
214 //NAN_CLUSTER_ATTRIBUTE
215 if (remainingLen <= 0) {
216 ALOGI("%s: No TLV's present",__func__);
217 return WIFI_SUCCESS;
218 }
219 ALOGI("%s: TLV remaining Len:%d",__func__, remainingLen);
220 while ((remainingLen > 0) &&
221 (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
222 ALOGI("%s: Remaining Len:%d readLen:%d type:%d length:%d",
223 __func__, remainingLen, readLen, outputTlv.type,
224 outputTlv.length);
225 switch (outputTlv.type) {
226 case NAN_TLV_TYPE_MAC_ADDRESS:
227 if (outputTlv.length > sizeof(event->addr)) {
228 outputTlv.length = sizeof(event->addr);
229 }
230 memcpy(event->addr, outputTlv.value, outputTlv.length);
231 break;
232 case NAN_TLV_TYPE_RECEIVED_RSSI_VALUE:
233 if (outputTlv.length > sizeof(event->rssi_value)) {
234 outputTlv.length = sizeof(event->rssi_value);
235 }
236 memcpy(&event->rssi_value, outputTlv.value,
237 outputTlv.length);
238 break;
239 case NAN_TLV_TYPE_POST_NAN_CONNECTIVITY_CAPABILITIES_RECEIVE:
240 if (outputTlv.length != sizeof(u32)) {
241 ALOGE("NAN_TLV_TYPE_POST_NAN_CONNECTIVITY_CAPABILITIES_RECEIVE"
242 "Incorrect size:%d expecting %d", outputTlv.length,
243 sizeof(u32));
244 break;
245 }
246 event->is_conn_capability_valid = 1;
247 /* Populate conn_capability from received TLV */
248 getNanReceivePostConnectivityCapabilityVal(outputTlv.value,
249 &event->conn_capability);
250 break;
251 case NAN_TLV_TYPE_POST_NAN_DISCOVERY_ATTRIBUTE_RECEIVE:
252 /* Populate receive discovery attribute from
253 received TLV */
254 ret = getNanReceivePostDiscoveryVal(outputTlv.value,
255 outputTlv.length,
256 &event->discovery_attr);
257 if (ret == 0) {
258 event->is_discovery_attr_valid = 1;
259 }
260 else {
261 ALOGE("NAN_TLV_TYPE_POST_NAN_DISCOVERY_ATTRIBUTE_RECEIVE"
262 "Incorrect");
263 }
264 break;
265 case NAN_TLV_TYPE_FURTHER_AVAILABILITY_MAP:
266 /* Populate further availability bitmap from
267 received TLV */
268 ret = getNanFurtherAvailabilityMap(outputTlv.value,
269 outputTlv.length,
270 &event->fam);
271 if (ret == 0) {
272 event->is_fam_valid = 1;
273 }
274 else {
275 ALOGE("NAN_TLV_TYPE_FURTHER_AVAILABILITY_MAP"
276 "Incorrect");
277 }
278 break;
279 case NAN_TLV_TYPE_CLUSTER_ATTIBUTE:
280 if (outputTlv.length > sizeof(event->cluster_attribute)) {
281 outputTlv.length = sizeof(event->cluster_attribute);
282 }
283 memcpy(event->cluster_attribute,
284 outputTlv.value, outputTlv.length);
285 event->cluster_attribute_len = outputTlv.length;
286 break;
287 default:
288 ALOGI("Unknown TLV type skipped");
289 break;
290 }
291 remainingLen -= readLen;
292 pInputTlv += readLen;
293 memset(&outputTlv, 0, sizeof(outputTlv));
294 }
295 #endif /* NAN_2_0 */
296 return WIFI_SUCCESS;
297 }
298
299
getNanPublishTerminated(NanPublishTerminatedInd * event)300 int NanCommand::getNanPublishTerminated(NanPublishTerminatedInd *event)
301 {
302 if (event == NULL || mNanVendorEvent == NULL) {
303 ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
304 __func__, event, mNanVendorEvent);
305 return WIFI_ERROR_INVALID_ARGS;
306 }
307
308 pNanPublishTerminatedIndMsg pRsp = (pNanPublishTerminatedIndMsg)mNanVendorEvent;
309 event->header.handle = pRsp->fwHeader.handle;
310 event->header.transaction_id = pRsp->fwHeader.transactionId;
311 #ifdef NAN_2_0
312 pRsp->reason -= NAN_TERMINATED_BEGINNING_OFFSET;
313 #endif /* NAN_2_0 */
314 event->reason = (NanTerminatedStatus)pRsp->reason;
315 return WIFI_SUCCESS;
316 }
317
getNanMatch(NanMatchInd * event)318 int NanCommand::getNanMatch(NanMatchInd *event)
319 {
320 if (event == NULL || mNanVendorEvent == NULL) {
321 ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
322 __func__, event, mNanVendorEvent);
323 return WIFI_ERROR_INVALID_ARGS;
324 }
325
326 pNanMatchIndMsg pRsp = (pNanMatchIndMsg)mNanVendorEvent;
327 event->header.handle = pRsp->fwHeader.handle;
328 event->header.transaction_id = pRsp->fwHeader.transactionId;
329 event->match_handle = pRsp->matchIndParams.matchHandle;
330 #ifndef NAN_2_0
331 memcpy(event->addr, pRsp->matchIndParams.macAddr, sizeof(event->addr));
332 #else /* NAN_2_0 */
333 event->match_occured_flag = pRsp->matchIndParams.matchOccuredFlag;
334 event->out_of_resource_flag = pRsp->matchIndParams.outOfResourceFlag;
335 #endif /* NAN_2_0 */
336
337 u8 *pInputTlv = pRsp->ptlv;
338 NanTlv outputTlv;
339 u16 readLen = 0;
340 int remainingLen = (mNanDataLen - \
341 (sizeof(NanMsgHeader) + sizeof(NanMatchIndParams)));
342 int ret = 0;
343
344 //Has SDF match filter and service specific info TLV
345 if (remainingLen <= 0) {
346 ALOGI("%s: No TLV's present",__func__);
347 return WIFI_SUCCESS;
348 }
349 ALOGI("%s: TLV remaining Len:%d",__func__, remainingLen);
350 while ((remainingLen > 0) &&
351 (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
352 ALOGI("%s: Remaining Len:%d readLen:%d type:%d length:%d",
353 __func__, remainingLen, readLen, outputTlv.type,
354 outputTlv.length);
355 switch (outputTlv.type) {
356 case NAN_TLV_TYPE_SERVICE_SPECIFIC_INFO:
357 if (outputTlv.length > NAN_MAX_SERVICE_NAME_LEN) {
358 outputTlv.length = NAN_MAX_SERVICE_NAME_LEN;
359 }
360 event->service_specific_info_len = outputTlv.length;
361 memcpy(event->service_specific_info, outputTlv.value,
362 outputTlv.length);
363 break;
364 case NAN_TLV_TYPE_SDF_MATCH_FILTER:
365 if (outputTlv.length > NAN_MAX_MATCH_FILTER_LEN) {
366 outputTlv.length = NAN_MAX_MATCH_FILTER_LEN;
367 }
368 event->sdf_match_filter_len = outputTlv.length;
369 memcpy(event->sdf_match_filter, outputTlv.value,
370 outputTlv.length);
371 break;
372 #ifdef NAN_2_0
373 case NAN_TLV_TYPE_MAC_ADDRESS:
374 if (outputTlv.length > sizeof(event->addr)) {
375 outputTlv.length = sizeof(event->addr);
376 }
377 memcpy(event->addr, outputTlv.value, outputTlv.length);
378 break;
379 case NAN_TLV_TYPE_RECEIVED_RSSI_VALUE:
380 if (outputTlv.length > sizeof(event->rssi_value)) {
381 outputTlv.length = sizeof(event->rssi_value);
382 }
383 memcpy(&event->rssi_value, outputTlv.value,
384 outputTlv.length);
385 break;
386 case NAN_TLV_TYPE_POST_NAN_CONNECTIVITY_CAPABILITIES_RECEIVE:
387 if (outputTlv.length != sizeof(u32)) {
388 ALOGE("NAN_TLV_TYPE_POST_NAN_CONNECTIVITY_CAPABILITIES_RECEIVE"
389 "Incorrect size:%d expecting %d", outputTlv.length,
390 sizeof(u32));
391 break;
392 }
393 event->is_conn_capability_valid = 1;
394 /* Populate conn_capability from received TLV */
395 getNanReceivePostConnectivityCapabilityVal(outputTlv.value,
396 &event->conn_capability);
397 break;
398 case NAN_TLV_TYPE_POST_NAN_DISCOVERY_ATTRIBUTE_RECEIVE:
399 /* Populate receive discovery attribute from
400 received TLV */
401 ret = getNanReceivePostDiscoveryVal(outputTlv.value,
402 outputTlv.length,
403 &event->discovery_attr);
404 if (ret == 0) {
405 event->is_discovery_attr_valid = 1;
406 }
407 else {
408 ALOGE("NAN_TLV_TYPE_POST_NAN_DISCOVERY_ATTRIBUTE_RECEIVE"
409 "Incorrect");
410 }
411 break;
412 case NAN_TLV_TYPE_FURTHER_AVAILABILITY_MAP:
413 /* Populate further availability bitmap from
414 received TLV */
415 ret = getNanFurtherAvailabilityMap(outputTlv.value,
416 outputTlv.length,
417 &event->fam);
418 if (ret == 0) {
419 event->is_fam_valid = 1;
420 }
421 else {
422 ALOGE("NAN_TLV_TYPE_FURTHER_AVAILABILITY_MAP"
423 "Incorrect");
424 }
425 break;
426 case NAN_TLV_TYPE_CLUSTER_ATTIBUTE:
427 if (outputTlv.length > sizeof(event->cluster_attribute)) {
428 outputTlv.length = sizeof(event->cluster_attribute);
429 }
430 memcpy(event->cluster_attribute,
431 outputTlv.value, outputTlv.length);
432 event->cluster_attribute_len = outputTlv.length;
433 break;
434 #endif /* NAN_2_0 */
435 default:
436 ALOGI("Unknown TLV type skipped");
437 break;
438 }
439 remainingLen -= readLen;
440 pInputTlv += readLen;
441 memset(&outputTlv, 0, sizeof(outputTlv));
442 }
443 return WIFI_SUCCESS;
444 }
445
getNanUnMatch(NanUnmatchInd * event)446 int NanCommand::getNanUnMatch(NanUnmatchInd *event)
447 {
448 if (event == NULL || mNanVendorEvent == NULL) {
449 ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
450 __func__, event, mNanVendorEvent);
451 return WIFI_ERROR_INVALID_ARGS;
452 }
453
454 pNanUnmatchIndMsg pRsp = (pNanUnmatchIndMsg)mNanVendorEvent;
455 event->header.handle = pRsp->fwHeader.handle;
456 event->header.transaction_id = pRsp->fwHeader.transactionId;
457 event->match_handle = pRsp->unmatchIndParams.matchHandle;
458 return WIFI_SUCCESS;
459 }
460
getNanSubscribeTerminated(NanSubscribeTerminatedInd * event)461 int NanCommand::getNanSubscribeTerminated(NanSubscribeTerminatedInd *event)
462 {
463 if (event == NULL || mNanVendorEvent == NULL) {
464 ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
465 __func__, event, mNanVendorEvent);
466 return WIFI_ERROR_INVALID_ARGS;
467 }
468
469 pNanSubscribeTerminatedIndMsg pRsp = (pNanSubscribeTerminatedIndMsg)mNanVendorEvent;
470 event->header.handle = pRsp->fwHeader.handle;
471 event->header.transaction_id = pRsp->fwHeader.transactionId;
472 #ifdef NAN_2_0
473 pRsp->reason -= NAN_TERMINATED_BEGINNING_OFFSET;
474 #endif /* NAN_2_0 */
475 event->reason = (NanTerminatedStatus)pRsp->reason;
476 return WIFI_SUCCESS;
477 }
478
getNanFollowup(NanFollowupInd * event)479 int NanCommand::getNanFollowup(NanFollowupInd *event)
480 {
481 if (event == NULL || mNanVendorEvent == NULL) {
482 ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
483 __func__, event, mNanVendorEvent);
484 return WIFI_ERROR_INVALID_ARGS;
485 }
486
487 pNanFollowupIndMsg pRsp = (pNanFollowupIndMsg)mNanVendorEvent;
488 event->header.handle = pRsp->fwHeader.handle;
489 event->header.transaction_id = pRsp->fwHeader.transactionId;
490 #ifndef NAN_2_0
491 memcpy(event->addr, pRsp->followupIndParams.macAddr, sizeof(event->addr));
492 #else /* NAN_2_0*/
493 event->match_handle = pRsp->followupIndParams.matchHandle;
494 #endif
495 event->dw_or_faw = pRsp->followupIndParams.window;
496
497 u8 *pInputTlv = pRsp->ptlv;
498 NanTlv outputTlv;
499 u16 readLen = 0;
500 int remainingLen = (mNanDataLen - \
501 (sizeof(NanMsgHeader) + sizeof(NanFollowupIndParams)));
502
503 //Has service specific info and extended service specific info TLV
504 if (remainingLen <= 0) {
505 ALOGI("%s: No TLV's present",__func__);
506 return WIFI_SUCCESS;
507 }
508 ALOGI("%s: TLV remaining Len:%d",__func__, remainingLen);
509 while ((remainingLen > 0) &&
510 (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
511 ALOGI("%s: Remaining Len:%d readLen:%d type:%d length:%d",
512 __func__, remainingLen, readLen, outputTlv.type,
513 outputTlv.length);
514 switch (outputTlv.type) {
515 case NAN_TLV_TYPE_SERVICE_SPECIFIC_INFO:
516 case NAN_TLV_TYPE_EXT_SERVICE_SPECIFIC_INFO:
517 if (outputTlv.length > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) {
518 outputTlv.length = NAN_MAX_SERVICE_SPECIFIC_INFO_LEN;
519 }
520 event->service_specific_info_len = outputTlv.length;
521 memcpy(event->service_specific_info, outputTlv.value,
522 outputTlv.length);
523 break;
524 #ifdef NAN_2_0
525 case NAN_TLV_TYPE_MAC_ADDRESS:
526 if (outputTlv.length > sizeof(event->addr)) {
527 outputTlv.length = sizeof(event->addr);
528 }
529 memcpy(event->addr, outputTlv.value, outputTlv.length);
530 break;
531 #endif /* NAN_2_0 */
532 default:
533 ALOGI("Unknown TLV type skipped");
534 break;
535 }
536 remainingLen -= readLen;
537 pInputTlv += readLen;
538 memset(&outputTlv, 0, sizeof(outputTlv));
539 }
540 return WIFI_SUCCESS;
541 }
542
getNanDiscEngEvent(NanDiscEngEventInd * event)543 int NanCommand::getNanDiscEngEvent(NanDiscEngEventInd *event)
544 {
545 if (event == NULL || mNanVendorEvent == NULL) {
546 ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
547 __func__, event, mNanVendorEvent);
548 return WIFI_ERROR_INVALID_ARGS;
549 }
550
551 pNanEventIndMsg pRsp = (pNanEventIndMsg)mNanVendorEvent;
552 event->header.handle = pRsp->fwHeader.handle;
553 event->header.transaction_id = pRsp->fwHeader.transactionId;
554 #ifndef NAN_2_0
555 event->event_id = (NanEventId)pRsp->eventIndParams.eventId;
556 #endif /* NAN_2_0 */
557 memset(&event->data, 0, sizeof(event->data));
558
559 u8 *pInputTlv = pRsp->ptlv;
560 NanTlv outputTlv;
561 u16 readLen = 0;
562 #ifndef NAN_2_0
563 int remainingLen = (mNanDataLen - \
564 (sizeof(NanMsgHeader) + sizeof(NanEventIndParams)));
565 #else /* NAN_2_0 */
566 int remainingLen = (mNanDataLen - \
567 (sizeof(NanMsgHeader)));
568 #endif /* NAN_2_0 */
569
570 //Has Self-STA Mac TLV
571 if (remainingLen <= 0) {
572 ALOGI("%s: No TLV's present",__func__);
573 return WIFI_SUCCESS;
574 }
575
576 ALOGI("%s: TLV remaining Len:%d event_id:%d",__func__,
577 remainingLen, event->event_id);
578 while ((remainingLen > 0) &&
579 (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
580 ALOGI("%s: Remaining Len:%d readLen:%d type:%d length:%d",
581 __func__, remainingLen, readLen, outputTlv.type,
582 outputTlv.length);
583 #ifdef NAN_2_0
584 event->event_id = (NanEventId)outputTlv.type;
585 #endif /* NAN_2_0 */
586 //Here we should check on the event_id
587 switch (event->event_id) {
588 case NAN_EVENT_ID_STA_MAC_ADDR:
589 if (outputTlv.length > NAN_MAC_ADDR_LEN) {
590 ALOGI("%s: Reading only first %d bytes of TLV",
591 __func__, NAN_MAC_ADDR_LEN);
592 outputTlv.length = NAN_MAC_ADDR_LEN;
593 }
594 memcpy(event->data.mac_addr.addr, outputTlv.value,
595 outputTlv.length);
596 break;
597 case NAN_EVENT_ID_STARTED_CLUSTER:
598 case NAN_EVENT_ID_JOINED_CLUSTER:
599 if (outputTlv.length > NAN_MAC_ADDR_LEN) {
600 ALOGI("%s: Reading only first %d bytes of TLV",
601 __func__, NAN_MAC_ADDR_LEN);
602 outputTlv.length = NAN_MAC_ADDR_LEN;
603 }
604 memcpy(event->data.cluster.addr, outputTlv.value,
605 outputTlv.length);
606 break;
607 default:
608 ALOGI("Unhandled eventId:%d", event->event_id);
609 break;
610 }
611 remainingLen -= readLen;
612 pInputTlv += readLen;
613 memset(&outputTlv,0, sizeof(outputTlv));
614 }
615 return WIFI_SUCCESS;
616 }
617
getNanDisabled(NanDisabledInd * event)618 int NanCommand::getNanDisabled(NanDisabledInd *event)
619 {
620 if (event == NULL || mNanVendorEvent == NULL) {
621 ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
622 __func__, event, mNanVendorEvent);
623 return WIFI_ERROR_INVALID_ARGS;
624 }
625
626 pNanDisableIndMsg pRsp = (pNanDisableIndMsg)mNanVendorEvent;
627 event->header.handle = pRsp->fwHeader.handle;
628 event->header.transaction_id = pRsp->fwHeader.transactionId;
629 event->reason = (NanStatusType)pRsp->reason;
630 return WIFI_SUCCESS;
631
632 }
633
getNanTca(NanTCAInd * event)634 int NanCommand::getNanTca(NanTCAInd *event)
635 {
636 if (event == NULL || mNanVendorEvent == NULL) {
637 ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
638 __func__, event, mNanVendorEvent);
639 return WIFI_ERROR_INVALID_ARGS;
640 }
641
642 pNanTcaIndMsg pRsp = (pNanTcaIndMsg)mNanVendorEvent;
643 event->header.handle = pRsp->fwHeader.handle;
644 event->header.transaction_id = pRsp->fwHeader.transactionId;
645 memset(&event->data, 0, sizeof(event->data));
646 #ifndef NAN_2_0
647 event->tca_id = (NanTcaId)pRsp->tcaIndParams.tcaId;
648 #else /* NAN_2_0 */
649 event->tca_id = (NanTcaId)0;
650 #endif /* NAN_2_0 */
651
652 u8 *pInputTlv = pRsp->ptlv;
653 NanTlv outputTlv;
654 u16 readLen = 0;
655 #ifndef NAN_2_0
656 int remainingLen = (mNanDataLen - \
657 (sizeof(NanMsgHeader) + sizeof(NanTcaIndParams)));
658 #else
659 int remainingLen = (mNanDataLen - \
660 (sizeof(NanMsgHeader)));
661 #endif
662
663 //Has NAN_TCA_ID_CLUSTER_SIZE
664 if (remainingLen <= 0) {
665 ALOGI("%s: No TLV's present",__func__);
666 return WIFI_SUCCESS;
667 }
668
669 ALOGI("%s: TLV remaining Len:%d tca_id:%d",__func__,
670 remainingLen, event->tca_id);
671 while ((remainingLen > 0) &&
672 (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
673 ALOGI("%s: Remaining Len:%d readLen:%d type:%d length:%d",
674 __func__, remainingLen, readLen, outputTlv.type,
675 outputTlv.length);
676 //Here we should check on the event_id
677 switch (event->tca_id) {
678 case NAN_TCA_ID_CLUSTER_SIZE:
679 #ifndef NAN_2_0
680 if (outputTlv.length > sizeof(event->data.cluster.cluster_size)) {
681 outputTlv.length = sizeof(event->data.cluster.cluster_size);
682 }
683 memcpy(&(event->data.cluster.cluster_size), outputTlv.value,
684 outputTlv.length);
685 #else /* NAN_2_0 */
686 if (outputTlv.length != 2 * sizeof(u32)) {
687 ALOGE("%s: Wrong length %d in Tca Indication expecting %d bytes",
688 __func__, outputTlv.length, 2 * sizeof(u32));
689 break;
690 }
691 event->rising_direction_evt_flag = outputTlv.value[0] & 0x01;
692 event->falling_direction_evt_flag = (outputTlv.value[0] & 0x02) >> 1;
693 memcpy(&(event->data.cluster.cluster_size), &outputTlv.value[4],
694 sizeof(event->data.cluster.cluster_size));
695 #endif /* NAN_2_0 */
696 break;
697 default:
698 ALOGI("Unhandled eventId:%d", event->tca_id);
699 break;
700 }
701 remainingLen -= readLen;
702 pInputTlv += readLen;
703 memset(&outputTlv,0, sizeof(outputTlv));
704 }
705 return WIFI_SUCCESS;
706 }
707
getNanBeaconSdfPayload(NanBeaconSdfPayloadInd * event)708 int NanCommand::getNanBeaconSdfPayload(NanBeaconSdfPayloadInd *event)
709 {
710 if (event == NULL || mNanVendorEvent == NULL) {
711 ALOGE("%s: Invalid input argument event:%p mNanVendorEvent:%p",
712 __func__, event, mNanVendorEvent);
713 return WIFI_ERROR_INVALID_ARGS;
714 }
715
716 #ifdef NAN_2_0
717 pNanBeaconSdfPayloadIndMsg pRsp = (pNanBeaconSdfPayloadIndMsg)mNanVendorEvent;
718 event->header.handle = pRsp->fwHeader.handle;
719 event->header.transaction_id = pRsp->fwHeader.transactionId;
720 memset(&event->data, 0, sizeof(event->data));
721
722 u8 *pInputTlv = pRsp->ptlv;
723 NanTlv outputTlv;
724 u16 readLen = 0;
725 int remainingLen = (mNanDataLen - \
726 (sizeof(NanMsgHeader)));
727
728 //Has Mac address
729 if (remainingLen <= 0) {
730 ALOGI("%s: No TLV's present",__func__);
731 return WIFI_SUCCESS;
732 }
733
734 ALOGI("%s: TLV remaining Len:%d",__func__, remainingLen);
735 while ((remainingLen > 0) &&
736 (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
737 ALOGI("%s: Remaining Len:%d readLen:%d type:%d length:%d",
738 __func__, remainingLen, readLen, outputTlv.type,
739 outputTlv.length);
740 //Here we should check on the event_id
741 switch (outputTlv.type) {
742 case NAN_TLV_TYPE_SELF_MAC_ADDR:
743 if (outputTlv.length > sizeof(event->addr)) {
744 outputTlv.length = sizeof(event->addr);
745 }
746 memcpy(event->addr, outputTlv.value,
747 outputTlv.length);
748 break;
749
750 case NAN_TLV_TYPE_VENDOR_SPECIFIC_ATTRIBUTE_RECEIVE:
751 {
752 NanReceiveVendorSpecificAttribute* recvVsaattr = &event->vsa;
753 if (outputTlv.length < sizeof(u32)) {
754 ALOGE("NAN_TLV_TYPE_VENDOR_SPECIFIC_ATTRIBUTE_RECEIVE"
755 "Incorrect length:%d", outputTlv.length);
756 break;
757 }
758 event->is_vsa_received = 1;
759 recvVsaattr->vsa_received_on = (outputTlv.value[0] >> 1) & 0x07;
760 memcpy(&recvVsaattr->vendor_oui, &outputTlv.value[1],
761 3);
762 recvVsaattr->attr_len = outputTlv.length - 4;
763 if (recvVsaattr->attr_len > NAN_MAX_VSA_DATA_LEN) {
764 recvVsaattr->attr_len = NAN_MAX_VSA_DATA_LEN;
765 }
766 if (recvVsaattr->attr_len) {
767 memcpy(recvVsaattr->vsa, &outputTlv.value[4],
768 recvVsaattr->attr_len);
769 }
770 break;
771 }
772
773 case NAN_TLV_TYPE_BEACON_SDF_PAYLOAD_RECEIVE:
774 event->is_beacon_sdf_payload_received = 1;
775 event->data.frame_len = outputTlv.length;
776 if (event->data.frame_len > NAN_MAX_VSA_DATA_LEN) {
777 event->data.frame_len = NAN_MAX_VSA_DATA_LEN;
778 }
779 memcpy(&event->data.frame_data, &outputTlv.value[0],
780 event->data.frame_len);
781 break;
782
783 default:
784 ALOGI("Unhandled TLV Type:%d", outputTlv.type);
785 break;
786 }
787 remainingLen -= readLen;
788 pInputTlv += readLen;
789 memset(&outputTlv,0, sizeof(outputTlv));
790 }
791 return WIFI_SUCCESS;
792 #else /* NAN_2_0 */
793 return WIFI_ERROR_INVALID_ARGS;
794 #endif /* NAN_2_0 */
795 }
796
getNanReceivePostConnectivityCapabilityVal(const u8 * pInValue,NanReceivePostConnectivityCapability * pRxCapab)797 void NanCommand::getNanReceivePostConnectivityCapabilityVal(
798 const u8 *pInValue,
799 NanReceivePostConnectivityCapability *pRxCapab)
800 {
801 if (pInValue && pRxCapab) {
802 pRxCapab->is_mesh_supported = (pInValue[0] && (0x01 << 5));
803 pRxCapab->is_ibss_supported = (pInValue[0] && (0x01 << 4));
804 pRxCapab->wlan_infra_field = (pInValue[0] && (0x01 << 3));
805 pRxCapab->is_tdls_supported = (pInValue[0] && (0x01 << 2));
806 pRxCapab->is_wfds_supported = (pInValue[0] && (0x01 << 1));
807 pRxCapab->is_wfd_supported = pInValue[0] && 0x01;
808 }
809 }
810
getNanReceivePostDiscoveryVal(const u8 * pInValue,u32 length,NanReceivePostDiscovery * pRxDisc)811 int NanCommand::getNanReceivePostDiscoveryVal(const u8 *pInValue,
812 u32 length,
813 NanReceivePostDiscovery *pRxDisc)
814 {
815 int ret = 0;
816
817 #ifdef NAN_2_0
818 if (length <= 8 || pInValue == NULL) {
819 ALOGE("%s: Invalid Arg TLV Len %d < 4",
820 __func__, length);
821 return -1;
822 }
823
824 pRxDisc->type = (NanConnectionType) pInValue[0];
825 pRxDisc->role = (NanDeviceRole) pInValue[1];
826 pRxDisc->duration = (NanAvailDuration) (pInValue[2] & 0x03);
827 pRxDisc->mapid = ((pInValue[2] >> 2) & 0x0F);
828 memcpy(&pRxDisc->avail_interval_bitmap,
829 &pInValue[4],
830 sizeof(pRxDisc->avail_interval_bitmap));
831
832 u8 *pInputTlv = (u8 *)&pInValue[8];
833 NanTlv outputTlv;
834 u16 readLen = 0;
835 int remainingLen = (length - 8);
836
837 //Has Mac address
838 if (remainingLen <= 0) {
839 ALOGE("%s: No TLV's present",__func__);
840 return -1;
841 }
842
843 ALOGI("%s: TLV remaining Len:%d",__func__, remainingLen);
844 while ((remainingLen > 0) &&
845 (0 != (readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv)))) {
846 ALOGI("%s: Remaining Len:%d readLen:%d type:%d length:%d",
847 __func__, remainingLen, readLen, outputTlv.type,
848 outputTlv.length);
849 switch (outputTlv.type) {
850 case NAN_TLV_TYPE_MAC_ADDRESS:
851 if (outputTlv.length > sizeof(pRxDisc->addr)) {
852 outputTlv.length = sizeof(pRxDisc->addr);
853 }
854 memcpy(pRxDisc->addr, outputTlv.value, outputTlv.length);
855 break;
856 case NAN_TLV_TYPE_WLAN_MESH_ID:
857 if (outputTlv.length > sizeof(pRxDisc->mesh_id)) {
858 outputTlv.length = sizeof(pRxDisc->mesh_id);
859 }
860 memcpy(pRxDisc->mesh_id, outputTlv.value, outputTlv.length);
861 pRxDisc->mesh_id_len = outputTlv.length;
862 break;
863 case NAN_TLV_TYPE_WLAN_INFRASTRUCTURE_SSID:
864 if (outputTlv.length > sizeof(pRxDisc->infrastructure_ssid_val)) {
865 outputTlv.length = sizeof(pRxDisc->infrastructure_ssid_val);
866 }
867 memcpy(pRxDisc->infrastructure_ssid_val, outputTlv.value,
868 outputTlv.length);
869 pRxDisc->infrastructure_ssid_len = outputTlv.length;
870 default:
871 ALOGI("Unhandled TLV Type:%d", outputTlv.type);
872 break;
873 }
874 remainingLen -= readLen;
875 pInputTlv += readLen;
876 memset(&outputTlv,0, sizeof(outputTlv));
877 }
878 #endif /* NAN_2_0 */
879 return ret;
880 }
881
getNanFurtherAvailabilityMap(const u8 * pInValue,u32 length,NanFurtherAvailabilityMap * pFam)882 int NanCommand::getNanFurtherAvailabilityMap(const u8 *pInValue,
883 u32 length,
884 NanFurtherAvailabilityMap *pFam)
885 {
886 #ifdef NAN_2_0
887 int idx = 0;
888
889 if ((length == 0) || pInValue == NULL) {
890 ALOGE("%s: Invalid Arg TLV Len %d or pInValue NULL",
891 __func__, length);
892 return -1;
893 }
894
895 pFam->numchans = pInValue[0];
896 if (pFam->numchans > NAN_MAX_FAM_CHANNELS) {
897 ALOGE("%s: Unable to accommodate numchans %d",
898 __func__, pFam->numchans);
899 return -1;
900 }
901
902 if (length < (sizeof(u8) +
903 (pFam->numchans * sizeof(NanFurtherAvailabilityChan)))) {
904 ALOGE("%s: Invalid TLV Length", __func__);
905 return -1;
906 }
907
908 for (idx = 0; idx < pFam->numchans; idx++) {
909 pNanFurtherAvailabilityChan pRsp = \
910 (pNanFurtherAvailabilityChan)((u8 *)&pInValue[1] + \
911 (idx * sizeof(NanFurtherAvailabilityChan)));
912 NanFurtherAvailabilityChannel *pFamChan = &pFam->famchan[idx];
913
914 pFamChan->entry_control = \
915 (NanAvailDuration)(pRsp->entryCtrl.availIntDuration);
916 pFamChan->mapid = pRsp->entryCtrl.mapId;
917 pFamChan->class_val = pRsp->opClass;
918 pFamChan->channel = pRsp->channel;
919 memcpy(&pFamChan->avail_interval_bitmap,
920 &pRsp->availIntBitmap,
921 sizeof(pFamChan->avail_interval_bitmap));
922 }
923 #endif /* NAN_2_0*/
924 return 0;
925 }
926
getNanStaParameter(NanStaParameter * pRsp)927 int NanCommand::getNanStaParameter(NanStaParameter *pRsp)
928 {
929 int ret = WIFI_ERROR_NONE;
930 int res = -1;
931
932 /*
933 Construct NL message to get the sync stats parameter
934 which has all the parameter required by staparameter.
935 */
936 NanStatsRequest syncStats;
937 memset(&syncStats, 0, sizeof(syncStats));
938 syncStats.header.handle = 0x0;
939 syncStats.header.transaction_id = 0x1234;
940 syncStats.stats_id = NAN_STATS_ID_DE_TIMING_SYNC;
941 syncStats.clear = 0;
942
943 mStaParam = pRsp;
944 ret = putNanStats(&syncStats);
945 if (ret != 0) {
946 ALOGE("%s: putNanStats Error:%d",__func__, ret);
947 goto cleanup;
948 }
949 ret = requestEvent();
950 if (ret != 0) {
951 ALOGE("%s: requestEvent Error:%d",__func__, ret);
952 goto cleanup;
953 }
954
955 struct timespec abstime;
956 abstime.tv_sec = 4;
957 abstime.tv_nsec = 0;
958 res = mCondition.wait(abstime);
959 if (res == ETIMEDOUT)
960 {
961 ALOGE("%s: Time out happened.", __func__);
962 ret = WIFI_ERROR_TIMED_OUT;
963 goto cleanup;
964 }
965 ALOGI("%s: NanStaparameter Master_pref:%x," \
966 " Random_factor:%x, hop_count:%x " \
967 " beacon_transmit_time:%d", __func__,
968 pRsp->master_pref, pRsp->random_factor,
969 pRsp->hop_count, pRsp->beacon_transmit_time);
970 cleanup:
971 mStaParam = NULL;
972 return (int)ret;
973 }
974