• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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