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