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