blob: bec2dddc36d26332550187bdbc2817eadf69f70b [file] [log] [blame]
#include <stdint.h>
#include <stddef.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/family.h>
#include <netlink/genl/ctrl.h>
#include <linux/rtnetlink.h>
#include <netpacket/packet.h>
#include <linux/filter.h>
#include <linux/errqueue.h>
#include <linux/pkt_sched.h>
#include <netlink/object-api.h>
#include <netlink/netlink.h>
#include <netlink/socket.h>
#include <netlink/handlers.h>
#include "sync.h"
#include <utils/Log.h>
#include "wifi_hal.h"
#include "common.h"
#include "cpp_bindings.h"
#define SLSI_WIFI_HAL_NAN_VERSION 1
#define CHECK_WIFI_STATUS_RETURN_FAIL(result, LOGSTR) \
if (result != WIFI_SUCCESS) {\
ALOGE(LOGSTR" [result:%d]", result);\
return result;\
}
#define CHECK_CONFIG_PUT_8_RETURN_FAIL(config, val, nan_attribute, request, result, FAIL_STR) \
if (config) {\
result = request.put_u8(nan_attribute, val); \
if (result != WIFI_SUCCESS) {\
ALOGE(FAIL_STR" [result:%d]", result);\
return result;\
}\
}
#define CHECK_CONFIG_PUT_16_RETURN_FAIL(config, val, nan_attribute, request, result, FAIL_STR) \
if (config) {\
result = request.put_u16(nan_attribute, val); \
if (result != WIFI_SUCCESS) {\
ALOGE(FAIL_STR" [result:%d]", result);\
return result;\
}\
}
#define CHECK_CONFIG_PUT_32_RETURN_FAIL(config, val, nan_attribute, request, result, FAIL_STR) \
if (config) {\
result = request.put_u32(nan_attribute, val); \
if (result != WIFI_SUCCESS) {\
ALOGE(FAIL_STR" [result:%d]", result);\
return result;\
}\
}
#define CHECK_CONFIG_PUT_RETURN_FAIL(config, valptr, len, nan_attribute, request, result, FAIL_STR) \
if (config) {\
result = request.put(nan_attribute, valptr, len); \
if (result != WIFI_SUCCESS) {\
ALOGE(FAIL_STR" [result:%d]", result);\
return result;\
}\
}
typedef enum {
NAN_REQ_ATTR_MASTER_PREF,
NAN_REQ_ATTR_CLUSTER_LOW,
NAN_REQ_ATTR_CLUSTER_HIGH,
NAN_REQ_ATTR_HOP_COUNT_LIMIT_VAL,
NAN_REQ_ATTR_SID_BEACON_VAL,
NAN_REQ_ATTR_SUPPORT_2G4_VAL,
NAN_REQ_ATTR_SUPPORT_5G_VAL,
NAN_REQ_ATTR_RSSI_CLOSE_2G4_VAL,
NAN_REQ_ATTR_RSSI_MIDDLE_2G4_VAL,
NAN_REQ_ATTR_RSSI_PROXIMITY_2G4_VAL,
NAN_REQ_ATTR_BEACONS_2G4_VAL,
NAN_REQ_ATTR_SDF_2G4_VAL,
NAN_REQ_ATTR_CHANNEL_2G4_MHZ_VAL,
NAN_REQ_ATTR_RSSI_PROXIMITY_VAL,
NAN_REQ_ATTR_RSSI_CLOSE_5G_VAL,
NAN_REQ_ATTR_RSSI_CLOSE_PROXIMITY_5G_VAL,
NAN_REQ_ATTR_RSSI_MIDDLE_5G_VAL,
NAN_REQ_ATTR_RSSI_PROXIMITY_5G_VAL,
NAN_REQ_ATTR_BEACON_5G_VAL,
NAN_REQ_ATTR_SDF_5G_VAL,
NAN_REQ_ATTR_CHANNEL_5G_MHZ_VAL,
NAN_REQ_ATTR_RSSI_WINDOW_SIZE_VAL,
NAN_REQ_ATTR_OUI_VAL,
NAN_REQ_ATTR_MAC_ADDR_VAL,
NAN_REQ_ATTR_CLUSTER_VAL,
NAN_REQ_ATTR_SOCIAL_CH_SCAN_DWELL_TIME,
NAN_REQ_ATTR_SOCIAL_CH_SCAN_PERIOD,
NAN_REQ_ATTR_RANDOM_FACTOR_FORCE_VAL,
NAN_REQ_ATTR_HOP_COUNT_FORCE_VAL,
NAN_REQ_ATTR_CONN_CAPABILITY_PAYLOAD_TX,
NAN_REQ_ATTR_CONN_CAPABILITY_IBSS,
NAN_REQ_ATTR_CONN_CAPABILITY_WFD,
NAN_REQ_ATTR_CONN_CAPABILITY_WFDS,
NAN_REQ_ATTR_CONN_CAPABILITY_TDLS,
NAN_REQ_ATTR_CONN_CAPABILITY_MESH,
NAN_REQ_ATTR_CONN_CAPABILITY_WLAN_INFRA,
NAN_REQ_ATTR_DISCOVERY_ATTR_NUM_ENTRIES,
NAN_REQ_ATTR_DISCOVERY_ATTR_VAL,
NAN_REQ_ATTR_CONN_TYPE,
NAN_REQ_ATTR_NAN_ROLE,
NAN_REQ_ATTR_TRANSMIT_FREQ,
NAN_REQ_ATTR_AVAILABILITY_DURATION,
NAN_REQ_ATTR_AVAILABILITY_INTERVAL,
NAN_REQ_ATTR_MESH_ID_LEN,
NAN_REQ_ATTR_MESH_ID,
NAN_REQ_ATTR_INFRASTRUCTURE_SSID_LEN,
NAN_REQ_ATTR_INFRASTRUCTURE_SSID,
NAN_REQ_ATTR_FURTHER_AVAIL_NUM_ENTRIES,
NAN_REQ_ATTR_FURTHER_AVAIL_VAL,
NAN_REQ_ATTR_FURTHER_AVAIL_ENTRY_CTRL,
NAN_REQ_ATTR_FURTHER_AVAIL_CHAN_CLASS,
NAN_REQ_ATTR_FURTHER_AVAIL_CHAN,
NAN_REQ_ATTR_FURTHER_AVAIL_CHAN_MAPID,
NAN_REQ_ATTR_FURTHER_AVAIL_INTERVAL_BITMAP,
NAN_REQ_ATTR_PUBLISH_ID,
NAN_REQ_ATTR_PUBLISH_TTL,
NAN_REQ_ATTR_PUBLISH_PERIOD,
NAN_REQ_ATTR_PUBLISH_TYPE,
NAN_REQ_ATTR_PUBLISH_TX_TYPE,
NAN_REQ_ATTR_PUBLISH_COUNT,
NAN_REQ_ATTR_PUBLISH_SERVICE_NAME_LEN,
NAN_REQ_ATTR_PUBLISH_SERVICE_NAME,
NAN_REQ_ATTR_PUBLISH_MATCH_ALGO,
NAN_REQ_ATTR_PUBLISH_SERVICE_INFO_LEN,
NAN_REQ_ATTR_PUBLISH_SERVICE_INFO,
NAN_REQ_ATTR_PUBLISH_RX_MATCH_FILTER_LEN,
NAN_REQ_ATTR_PUBLISH_RX_MATCH_FILTER,
NAN_REQ_ATTR_PUBLISH_TX_MATCH_FILTER_LEN,
NAN_REQ_ATTR_PUBLISH_TX_MATCH_FILTER,
NAN_REQ_ATTR_PUBLISH_RSSI_THRESHOLD_FLAG,
NAN_REQ_ATTR_PUBLISH_CONN_MAP,
NAN_REQ_ATTR_PUBLISH_RECV_IND_CFG,
NAN_REQ_ATTR_SUBSCRIBE_ID,
NAN_REQ_ATTR_SUBSCRIBE_TTL,
NAN_REQ_ATTR_SUBSCRIBE_PERIOD,
NAN_REQ_ATTR_SUBSCRIBE_TYPE,
NAN_REQ_ATTR_SUBSCRIBE_RESP_FILTER_TYPE,
NAN_REQ_ATTR_SUBSCRIBE_RESP_INCLUDE,
NAN_REQ_ATTR_SUBSCRIBE_USE_RESP_FILTER,
NAN_REQ_ATTR_SUBSCRIBE_SSI_REQUIRED,
NAN_REQ_ATTR_SUBSCRIBE_MATCH_INDICATOR,
NAN_REQ_ATTR_SUBSCRIBE_COUNT,
NAN_REQ_ATTR_SUBSCRIBE_SERVICE_NAME_LEN,
NAN_REQ_ATTR_SUBSCRIBE_SERVICE_NAME,
NAN_REQ_ATTR_SUBSCRIBE_SERVICE_INFO_LEN,
NAN_REQ_ATTR_SUBSCRIBE_SERVICE_INFO,
NAN_REQ_ATTR_SUBSCRIBE_RX_MATCH_FILTER_LEN,
NAN_REQ_ATTR_SUBSCRIBE_RX_MATCH_FILTER,
NAN_REQ_ATTR_SUBSCRIBE_TX_MATCH_FILTER_LEN,
NAN_REQ_ATTR_SUBSCRIBE_TX_MATCH_FILTER,
NAN_REQ_ATTR_SUBSCRIBE_RSSI_THRESHOLD_FLAG,
NAN_REQ_ATTR_SUBSCRIBE_CONN_MAP,
NAN_REQ_ATTR_SUBSCRIBE_NUM_INTF_ADDR_PRESENT,
NAN_REQ_ATTR_SUBSCRIBE_INTF_ADDR,
NAN_REQ_ATTR_SUBSCRIBE_RECV_IND_CFG,
NAN_REQ_ATTR_FOLLOWUP_ID,
NAN_REQ_ATTR_FOLLOWUP_REQUESTOR_ID,
NAN_REQ_ATTR_FOLLOWUP_ADDR,
NAN_REQ_ATTR_FOLLOWUP_PRIORITY,
NAN_REQ_ATTR_FOLLOWUP_SERVICE_NAME_LEN,
NAN_REQ_ATTR_FOLLOWUP_SERVICE_NAME,
NAN_REQ_ATTR_FOLLOWUP_TX_WINDOW,
NAN_REQ_ATTR_FOLLOWUP_RECV_IND_CFG,
NAN_REQ_ATTR_SUBSCRIBE_SID_BEACON_VAL,
NAN_REQ_ATTR_DW_2G4_INTERVAL,
NAN_REQ_ATTR_DW_5G_INTERVAL,
NAN_REQ_ATTR_DISC_MAC_ADDR_RANDOM_INTERVAL,
NAN_REQ_ATTR_PUBLISH_SDEA_LEN,
NAN_REQ_ATTR_PUBLISH_SDEA,
NAN_REQ_ATTR_RANGING_AUTO_RESPONSE,
NAN_REQ_ATTR_SDEA_PARAM_NDP_TYPE,
NAN_REQ_ATTR_SDEA_PARAM_SECURITY_CFG,
NAN_REQ_ATTR_SDEA_PARAM_RANGING_STATE,
NAN_REQ_ATTR_SDEA_PARAM_RANGE_REPORT,
NAN_REQ_ATTR_SDEA_PARAM_QOS_CFG,
NAN_REQ_ATTR_RANGING_CFG_INTERVAL,
NAN_REQ_ATTR_RANGING_CFG_INDICATION,
NAN_REQ_ATTR_RANGING_CFG_INGRESS_MM,
NAN_REQ_ATTR_RANGING_CFG_EGRESS_MM,
NAN_REQ_ATTR_CIPHER_TYPE,
NAN_REQ_ATTR_SCID_LEN,
NAN_REQ_ATTR_SCID,
NAN_REQ_ATTR_SECURITY_KEY_TYPE,
NAN_REQ_ATTR_SECURITY_PMK_LEN,
NAN_REQ_ATTR_SECURITY_PMK,
NAN_REQ_ATTR_SECURITY_PASSPHRASE_LEN,
NAN_REQ_ATTR_SECURITY_PASSPHRASE,
NAN_REQ_ATTR_RANGE_RESPONSE_CFG_PUBLISH_ID,
NAN_REQ_ATTR_RANGE_RESPONSE_CFG_REQUESTOR_ID,
NAN_REQ_ATTR_RANGE_RESPONSE_CFG_PEER_ADDR,
NAN_REQ_ATTR_RANGE_RESPONSE_CFG_RANGING_RESPONSE
} NAN_REQ_ATTRIBUTES;
typedef enum {
NAN_REPLY_ATTR_STATUS_TYPE,
NAN_REPLY_ATTR_VALUE,
NAN_REPLY_ATTR_RESPONSE_TYPE,
NAN_REPLY_ATTR_PUBLISH_SUBSCRIBE_TYPE,
NAN_REPLY_ATTR_CAP_MAX_CONCURRENT_CLUSTER,
NAN_REPLY_ATTR_CAP_MAX_PUBLISHES,
NAN_REPLY_ATTR_CAP_MAX_SUBSCRIBES,
NAN_REPLY_ATTR_CAP_MAX_SERVICE_NAME_LEN,
NAN_REPLY_ATTR_CAP_MAX_MATCH_FILTER_LEN,
NAN_REPLY_ATTR_CAP_MAX_TOTAL_MATCH_FILTER_LEN,
NAN_REPLY_ATTR_CAP_MAX_SERVICE_SPECIFIC_INFO_LEN,
NAN_REPLY_ATTR_CAP_MAX_VSA_DATA_LEN,
NAN_REPLY_ATTR_CAP_MAX_MESH_DATA_LEN,
NAN_REPLY_ATTR_CAP_MAX_NDI_INTERFACES,
NAN_REPLY_ATTR_CAP_MAX_NDP_SESSIONS,
NAN_REPLY_ATTR_CAP_MAX_APP_INFO_LEN,
} NAN_RESP_ATTRIBUTES;
typedef enum {
NAN_EVT_ATTR_MATCH_PUBLISH_SUBSCRIBE_ID = 0,
NAN_EVT_ATTR_MATCH_REQUESTOR_INSTANCE_ID,
NAN_EVT_ATTR_MATCH_ADDR,
NAN_EVT_ATTR_MATCH_SERVICE_SPECIFIC_INFO_LEN,
NAN_EVT_ATTR_MATCH_SERVICE_SPECIFIC_INFO,
NAN_EVT_ATTR_MATCH_SDF_MATCH_FILTER_LEN,
NAN_EVT_ATTR_MATCH_SDF_MATCH_FILTER,
NAN_EVT_ATTR_MATCH_MATCH_OCCURED_FLAG,
NAN_EVT_ATTR_MATCH_OUT_OF_RESOURCE_FLAG,
NAN_EVT_ATTR_MATCH_RSSI_VALUE,
/*CONN_CAPABILITY*/
NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_WFD_SUPPORTED = 10,
NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_WFDS_SUPPORTED,
NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_TDLS_SUPPORTED,
NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_IBSS_SUPPORTED,
NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_MESH_SUPPORTED,
NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_WLAN_INFRA_FIELD,
NAN_EVT_ATTR_MATCH_NUM_RX_DISCOVERY_ATTR,
NAN_EVT_ATTR_MATCH_RX_DISCOVERY_ATTR,
/*NANRECEIVEPOSTDISCOVERY DISCOVERY_ATTR,*/
NAN_EVT_ATTR_MATCH_DISC_ATTR_TYPE,
NAN_EVT_ATTR_MATCH_DISC_ATTR_ROLE,
NAN_EVT_ATTR_MATCH_DISC_ATTR_DURATION = 20,
NAN_EVT_ATTR_MATCH_DISC_ATTR_AVAIL_INTERVAL_BITMAP,
NAN_EVT_ATTR_MATCH_DISC_ATTR_MAPID,
NAN_EVT_ATTR_MATCH_DISC_ATTR_ADDR,
NAN_EVT_ATTR_MATCH_DISC_ATTR_MESH_ID_LEN,
NAN_EVT_ATTR_MATCH_DISC_ATTR_MESH_ID,
NAN_EVT_ATTR_MATCH_DISC_ATTR_INFRASTRUCTURE_SSID_LEN,
NAN_EVT_ATTR_MATCH_DISC_ATTR_INFRASTRUCTURE_SSID_VAL,
NAN_EVT_ATTR_MATCH_NUM_CHANS,
NAN_EVT_ATTR_MATCH_FAMCHAN,
/*FAMCHAN[32],*/
NAN_EVT_ATTR_MATCH_FAM_ENTRY_CONTROL = 30,
NAN_EVT_ATTR_MATCH_FAM_CLASS_VAL,
NAN_EVT_ATTR_MATCH_FAM_CHANNEL,
NAN_EVT_ATTR_MATCH_FAM_MAPID,
NAN_EVT_ATTR_MATCH_FAM_AVAIL_INTERVAL_BITMAP,
NAN_EVT_ATTR_MATCH_CLUSTER_ATTRIBUTE_LEN,
NAN_EVT_ATTR_MATCH_CLUSTER_ATTRIBUTE,
NAN_EVT_ATTR_PUBLISH_ID,
NAN_EVT_ATTR_PUBLISH_REASON,
NAN_EVT_ATTR_SUBSCRIBE_ID,
NAN_EVT_ATTR_SUBSCRIBE_REASON = 40,
NAN_EVT_ATTR_DISABLED_REASON,
NAN_EVT_ATTR_FOLLOWUP_PUBLISH_SUBSCRIBE_ID,
NAN_EVT_ATTR_FOLLOWUP_REQUESTOR_INSTANCE_ID,
NAN_EVT_ATTR_FOLLOWUP_ADDR,
NAN_EVT_ATTR_FOLLOWUP_DW_OR_FAW,
NAN_EVT_ATTR_FOLLOWUP_SERVICE_SPECIFIC_INFO_LEN,
NAN_EVT_ATTR_FOLLOWUP_SERVICE_SPECIFIC_INFO,
NAN_EVT_ATTR_DISCOVERY_ENGINE_EVT_TYPE ,
NAN_EVT_ATTR_DISCOVERY_ENGINE_MAC_ADDR,
NAN_EVT_ATTR_DISCOVERY_ENGINE_CLUSTER = 50,
NAN_EVT_ATTR_SDEA,
NAN_EVT_ATTR_SDEA_LEN,
NAN_EVT_ATTR_SCID,
NAN_EVT_ATTR_SCID_LEN,
NAN_EVT_ATTR_SDEA_PARAM_CONFIG_NAN_DATA_PATH,
NAN_EVT_ATTR_SDEA_PARAM_NDP_TYPE,
NAN_EVT_ATTR_SDEA_PARAM_SECURITY_CONFIG,
NAN_EVT_ATTR_SDEA_PARAM_RANGE_STATE,
NAN_EVT_ATTR_SDEA_PARAM_RANGE_REPORT,
NAN_EVT_ATTR_SDEA_PARAM_QOS_CFG = 60,
NAN_EVT_ATTR_RANGE_MEASUREMENT_MM,
NAN_EVT_ATTR_RANGEING_EVENT_TYPE,
NAN_EVT_ATTR_SECURITY_CIPHER_TYPE,
NAN_EVT_ATTR_STATUS
} NAN_EVT_ATTRIBUTES;
class NanCommand : public WifiCommand {
static NanCallbackHandler callbackEventHandler;
int subscribeID[2];
int publishID[2];
int followupID[2];
transaction_id followupTid;
transaction_id publishTid;
transaction_id publishCancelTid;
transaction_id subscribeTid;
transaction_id subscribeCancelTid;
transaction_id enableTid;
transaction_id disableTid;
transaction_id configTid;
transaction_id capabilitiesTid;
int version;
NanCapabilities capabilities;
void registerNanEvents(void) {
registerVendorHandler(GOOGLE_OUI, SLSI_NAN_EVENT_PUBLISH_TERMINATED);
registerVendorHandler(GOOGLE_OUI, SLSI_NAN_EVENT_MATCH);
registerVendorHandler(GOOGLE_OUI, SLSI_NAN_EVENT_MATCH_EXPIRED);
registerVendorHandler(GOOGLE_OUI, SLSI_NAN_EVENT_SUBSCRIBE_TERMINATED);
registerVendorHandler(GOOGLE_OUI, SLSI_NAN_EVENT_FOLLOWUP);
registerVendorHandler(GOOGLE_OUI, SLSI_NAN_EVENT_DISCOVERY_ENGINE);
registerVendorHandler(GOOGLE_OUI, SLSI_NAN_EVENT_TRANSMIT_FOLLOWUP_STATUS);
}
void unregisterNanEvents(void) {
unregisterVendorHandler(GOOGLE_OUI, SLSI_NAN_EVENT_PUBLISH_TERMINATED);
unregisterVendorHandler(GOOGLE_OUI, SLSI_NAN_EVENT_MATCH);
unregisterVendorHandler(GOOGLE_OUI, SLSI_NAN_EVENT_MATCH_EXPIRED);
unregisterVendorHandler(GOOGLE_OUI, SLSI_NAN_EVENT_SUBSCRIBE_TERMINATED);
unregisterVendorHandler(GOOGLE_OUI, SLSI_NAN_EVENT_FOLLOWUP);
unregisterVendorHandler(GOOGLE_OUI, SLSI_NAN_EVENT_DISCOVERY_ENGINE);
unregisterVendorHandler(GOOGLE_OUI, SLSI_NAN_EVENT_TRANSMIT_FOLLOWUP_STATUS);
}
int processResponse(WifiEvent &reply, NanResponseMsg *response) {
NanCapabilities *capabilities = &response->body.nan_capabilities;
nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
unsigned int val;
for(nl_iterator nl_itr(vendor_data); nl_itr.has_next(); nl_itr.next()) {
switch(nl_itr.get_type()) {
case NAN_REPLY_ATTR_STATUS_TYPE:
response->status = NanStatusType(nl_itr.get_u32());
break;
case NAN_REPLY_ATTR_VALUE:
val = nl_itr.get_u32();
if (val) {
strncpy(response->nan_error, "Lower_layer_error",NAN_ERROR_STR_LEN);
}
break;
case NAN_REPLY_ATTR_RESPONSE_TYPE:
response->response_type = NanResponseType(nl_itr.get_u32());
break;
case NAN_REPLY_ATTR_PUBLISH_SUBSCRIBE_TYPE:
response->body.publish_response.publish_id = nl_itr.get_u16();
break;
case NAN_REPLY_ATTR_CAP_MAX_CONCURRENT_CLUSTER:
capabilities->max_concurrent_nan_clusters = nl_itr.get_u32();
break;
case NAN_REPLY_ATTR_CAP_MAX_PUBLISHES:
capabilities->max_publishes = nl_itr.get_u32();
break;
case NAN_REPLY_ATTR_CAP_MAX_SUBSCRIBES:
capabilities->max_subscribes = nl_itr.get_u32();
break;
case NAN_REPLY_ATTR_CAP_MAX_SERVICE_NAME_LEN:
capabilities->max_service_name_len = nl_itr.get_u32();
break;
case NAN_REPLY_ATTR_CAP_MAX_MATCH_FILTER_LEN:
capabilities->max_match_filter_len = nl_itr.get_u32();
break;
case NAN_REPLY_ATTR_CAP_MAX_TOTAL_MATCH_FILTER_LEN:
capabilities->max_total_match_filter_len = nl_itr.get_u32();
break;
case NAN_REPLY_ATTR_CAP_MAX_SERVICE_SPECIFIC_INFO_LEN:
capabilities->max_service_specific_info_len = nl_itr.get_u32();
break;
case NAN_REPLY_ATTR_CAP_MAX_VSA_DATA_LEN:
capabilities->max_vsa_data_len = nl_itr.get_u32();
break;
case NAN_REPLY_ATTR_CAP_MAX_MESH_DATA_LEN:
capabilities->max_mesh_data_len = nl_itr.get_u32();
break;
case NAN_REPLY_ATTR_CAP_MAX_NDI_INTERFACES:
capabilities->max_ndi_interfaces = nl_itr.get_u32();
break;
case NAN_REPLY_ATTR_CAP_MAX_NDP_SESSIONS:
capabilities->max_ndp_sessions = nl_itr.get_u32();
break;
case NAN_REPLY_ATTR_CAP_MAX_APP_INFO_LEN:
capabilities->max_app_info_len = nl_itr.get_u32();
break;
default :
ALOGE("received unknown type(%d) in response", nl_itr.get_type());
return NL_SKIP;
}
}
this->capabilities = *capabilities;
return NL_OK;
}
int processMatchEvent(WifiEvent &event) {
NanMatchInd ind;
memset(&ind,0,sizeof(NanMatchInd));
int famchan_idx = 0, disc_idx = 0;
nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
for(nl_iterator nl_itr(vendor_data); nl_itr.has_next(); nl_itr.next()) {
switch(nl_itr.get_type()) {
case NAN_EVT_ATTR_MATCH_PUBLISH_SUBSCRIBE_ID:
ind.publish_subscribe_id = nl_itr.get_u16();
break;
case NAN_EVT_ATTR_MATCH_REQUESTOR_INSTANCE_ID:
ind.requestor_instance_id = nl_itr.get_u32();
break;
case NAN_EVT_ATTR_MATCH_ADDR:
memcpy(ind.addr, nl_itr.get_data(), NAN_MAC_ADDR_LEN);
break;
case NAN_EVT_ATTR_MATCH_SERVICE_SPECIFIC_INFO_LEN:
ind.service_specific_info_len = nl_itr.get_u16();
break;
case NAN_EVT_ATTR_MATCH_SERVICE_SPECIFIC_INFO:
memcpy(ind.service_specific_info, nl_itr.get_data(), ind.service_specific_info_len);
break;
case NAN_EVT_ATTR_MATCH_SDF_MATCH_FILTER_LEN:
ind.sdf_match_filter_len = nl_itr.get_u16();
break;
case NAN_EVT_ATTR_MATCH_SDF_MATCH_FILTER:
memcpy(ind.sdf_match_filter, nl_itr.get_data(), ind.sdf_match_filter_len);
break;
case NAN_EVT_ATTR_MATCH_MATCH_OCCURED_FLAG:
ind.match_occured_flag = nl_itr.get_u8();
break;
case NAN_EVT_ATTR_MATCH_OUT_OF_RESOURCE_FLAG:
ind.out_of_resource_flag = nl_itr.get_u8();
break;
case NAN_EVT_ATTR_MATCH_RSSI_VALUE:
ind.rssi_value = nl_itr.get_u8();
break;
case NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_IBSS_SUPPORTED:
ind.conn_capability.is_ibss_supported = nl_itr.get_u8();
break;
case NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_WFD_SUPPORTED:
ind.conn_capability.is_wfd_supported = nl_itr.get_u8();
break;
case NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_WFDS_SUPPORTED:
ind.conn_capability.is_wfds_supported = nl_itr.get_u8();
break;
case NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_TDLS_SUPPORTED:
ind.conn_capability.is_tdls_supported = nl_itr.get_u8();
break;
case NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_MESH_SUPPORTED:
ind.conn_capability.is_mesh_supported= nl_itr.get_u8();
break;
case NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_WLAN_INFRA_FIELD:
ind.conn_capability.wlan_infra_field = nl_itr.get_u8();
break;
case NAN_EVT_ATTR_MATCH_NUM_RX_DISCOVERY_ATTR:
ind.num_rx_discovery_attr = nl_itr.get_u8();
break;
case NAN_EVT_ATTR_MATCH_RX_DISCOVERY_ATTR:
NanReceivePostDiscovery *disc_attr;
disc_attr = &ind.discovery_attr[disc_idx];
disc_idx++;
for(nl_iterator nl_nested_itr((struct nlattr *)nl_itr.get_data()); nl_nested_itr.has_next(); nl_nested_itr.next()) {
switch(nl_nested_itr.get_type()) {
case NAN_EVT_ATTR_MATCH_DISC_ATTR_TYPE:
disc_attr->type = (NanConnectionType)nl_nested_itr.get_u8();
break;
case NAN_EVT_ATTR_MATCH_DISC_ATTR_ROLE:
disc_attr->role = (NanDeviceRole)nl_nested_itr.get_u8();
break;
case NAN_EVT_ATTR_MATCH_DISC_ATTR_DURATION:
disc_attr->duration = (NanAvailDuration)nl_nested_itr.get_u8();
break;
case NAN_EVT_ATTR_MATCH_DISC_ATTR_AVAIL_INTERVAL_BITMAP:
disc_attr->avail_interval_bitmap = nl_nested_itr.get_u32();
break;
case NAN_EVT_ATTR_MATCH_DISC_ATTR_MAPID:
disc_attr->mapid = nl_nested_itr.get_u8();
break;
case NAN_EVT_ATTR_MATCH_DISC_ATTR_ADDR:
memcpy(disc_attr->addr, nl_nested_itr.get_data(), NAN_MAC_ADDR_LEN);
break;
case NAN_EVT_ATTR_MATCH_DISC_ATTR_MESH_ID_LEN:
disc_attr->mesh_id_len = nl_nested_itr.get_u8();
break;
case NAN_EVT_ATTR_MATCH_DISC_ATTR_MESH_ID:
memcpy(disc_attr->mesh_id, nl_nested_itr.get_data(), disc_attr->mesh_id_len);
break;
case NAN_EVT_ATTR_MATCH_DISC_ATTR_INFRASTRUCTURE_SSID_LEN:
disc_attr->infrastructure_ssid_len = nl_nested_itr.get_u16();
break;
case NAN_EVT_ATTR_MATCH_DISC_ATTR_INFRASTRUCTURE_SSID_VAL:
memcpy(disc_attr->infrastructure_ssid_val, nl_nested_itr.get_data(), disc_attr->infrastructure_ssid_len);
break;
}
}
break;
case NAN_EVT_ATTR_MATCH_NUM_CHANS:
ind.num_chans = nl_itr.get_u8();
break;
case NAN_EVT_ATTR_MATCH_FAMCHAN:
NanFurtherAvailabilityChannel *famchan;
famchan = &ind.famchan[famchan_idx];
famchan_idx++;
for(nl_iterator nl_nested_itr((struct nlattr *)nl_itr.get_data()); nl_nested_itr.has_next(); nl_nested_itr.next()) {
switch(nl_nested_itr.get_type()) {
case NAN_EVT_ATTR_MATCH_FAM_ENTRY_CONTROL:
famchan->entry_control = (NanAvailDuration)nl_nested_itr.get_u8();
break;
case NAN_EVT_ATTR_MATCH_FAM_CLASS_VAL:
famchan->class_val = nl_nested_itr.get_u8();
break;
case NAN_EVT_ATTR_MATCH_FAM_CHANNEL:
famchan->channel = nl_nested_itr.get_u8();
break;
case NAN_EVT_ATTR_MATCH_FAM_MAPID:
famchan->mapid = nl_nested_itr.get_u8();
break;
case NAN_EVT_ATTR_MATCH_FAM_AVAIL_INTERVAL_BITMAP:
famchan->avail_interval_bitmap = nl_nested_itr.get_u32();
break;
}
}
break;
case NAN_EVT_ATTR_MATCH_CLUSTER_ATTRIBUTE_LEN:
ind.cluster_attribute_len = nl_itr.get_u8();
break;
case NAN_EVT_ATTR_MATCH_CLUSTER_ATTRIBUTE:
memcpy(ind.cluster_attribute, nl_itr.get_data(), ind.cluster_attribute_len);
break;
case NAN_EVT_ATTR_SDEA_LEN:
ind.sdea_service_specific_info_len = nl_itr.get_u16();
break;
case NAN_EVT_ATTR_SDEA:
memcpy(ind.sdea_service_specific_info, nl_itr.get_data(), ind.sdea_service_specific_info_len);
break;
case NAN_EVT_ATTR_SCID_LEN:
ind.scid_len = nl_itr.get_u32();
break;
case NAN_EVT_ATTR_SCID:
memcpy(ind.scid, nl_itr.get_data(), ind.scid_len);
break;
case NAN_EVT_ATTR_SDEA_PARAM_CONFIG_NAN_DATA_PATH:
ind.peer_sdea_params.config_nan_data_path = nl_itr.get_u8();
break;
case NAN_EVT_ATTR_SDEA_PARAM_NDP_TYPE:
ind.peer_sdea_params.ndp_type = (NdpType)nl_itr.get_u8();
break;
case NAN_EVT_ATTR_SDEA_PARAM_SECURITY_CONFIG:
ind.peer_sdea_params.security_cfg = (NanDataPathSecurityCfgStatus)nl_itr.get_u8();
break;
case NAN_EVT_ATTR_SDEA_PARAM_RANGE_STATE:
ind.peer_sdea_params.ranging_state = (NanRangingState)nl_itr.get_u8();
break;
case NAN_EVT_ATTR_SDEA_PARAM_RANGE_REPORT:
ind.peer_sdea_params.range_report = (NanRangeReport)nl_itr.get_u8();
break;
case NAN_EVT_ATTR_SDEA_PARAM_QOS_CFG:
ind.peer_sdea_params.qos_cfg = (NanQosCfgStatus)nl_itr.get_u8();
break;
case NAN_EVT_ATTR_RANGE_MEASUREMENT_MM:
ind.range_info.range_measurement_mm = nl_itr.get_u32();
break;
case NAN_EVT_ATTR_RANGEING_EVENT_TYPE:
ind.range_info.ranging_event_type = nl_itr.get_u32();
break;
}
}
if (this->callbackEventHandler.EventMatch)
this->callbackEventHandler.EventMatch(&ind);
return NL_OK;
}
int processMatchExpiredEvent(WifiEvent &event) {
NanMatchExpiredInd ind;
memset(&ind,0,sizeof(NanMatchExpiredInd));
for(nl_iterator nl_itr((struct nlattr *)event.get_vendor_data()); nl_itr.has_next(); nl_itr.next()) {
switch(nl_itr.get_type()) {
case NAN_EVT_ATTR_MATCH_PUBLISH_SUBSCRIBE_ID:
ind.publish_subscribe_id = nl_itr.get_u16();
break;
case NAN_EVT_ATTR_MATCH_REQUESTOR_INSTANCE_ID:
ind.requestor_instance_id = nl_itr.get_u32();
break;
default :
ALOGE("processMatchExpiredEvent: unknown attribute(%d)", nl_itr.get_type());
return NL_SKIP;
}
}
if (callbackEventHandler.EventMatchExpired)
callbackEventHandler.EventMatchExpired(&ind);
return NL_OK;
}
int processPublishTerminatedEvent(WifiEvent &event) {
NanPublishTerminatedInd ind;
memset(&ind,0,sizeof(ind));
for(nl_iterator nl_itr((struct nlattr *)event.get_vendor_data()); nl_itr.has_next(); nl_itr.next()) {
switch(nl_itr.get_type()) {
case NAN_EVT_ATTR_PUBLISH_ID:
ind.publish_id = nl_itr.get_u16();
break;
case NAN_EVT_ATTR_PUBLISH_REASON:
ind.reason = (NanStatusType)nl_itr.get_u32();
break;
default :
ALOGE("processPublishTerminatedEvent: unknown attribute(%d)", nl_itr.get_type());
return NL_SKIP;
}
}
if (callbackEventHandler.EventPublishTerminated)
callbackEventHandler.EventPublishTerminated(&ind);
return NL_OK;
}
int processSubscribeTerminatedEvent(WifiEvent &event) {
NanSubscribeTerminatedInd ind;
memset(&ind,0,sizeof(ind));
for(nl_iterator nl_itr((struct nlattr *)event.get_vendor_data()); nl_itr.has_next(); nl_itr.next()) {
switch(nl_itr.get_type()) {
case NAN_EVT_ATTR_SUBSCRIBE_ID:
ind.subscribe_id = nl_itr.get_u16();
break;
case NAN_EVT_ATTR_SUBSCRIBE_REASON:
ind.reason = (NanStatusType)nl_itr.get_u32();
break;
default :
ALOGE("processSubscribeTerminatedEvent: unknown attribute(%d)", nl_itr.get_type());
return NL_SKIP;
}
}
if (callbackEventHandler.EventSubscribeTerminated)
callbackEventHandler.EventSubscribeTerminated(&ind);
return NL_OK;
}
int processFollowupEvent(WifiEvent &event) {
NanFollowupInd ind;
nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
memset(&ind,0,sizeof(ind));
for(nl_iterator nl_itr(vendor_data); nl_itr.has_next(); nl_itr.next()) {
switch(nl_itr.get_type()) {
case NAN_EVT_ATTR_FOLLOWUP_PUBLISH_SUBSCRIBE_ID:
ind.publish_subscribe_id = nl_itr.get_u16();
break;
case NAN_EVT_ATTR_FOLLOWUP_REQUESTOR_INSTANCE_ID:
ind.requestor_instance_id = nl_itr.get_u32();
break;
case NAN_EVT_ATTR_FOLLOWUP_ADDR:
memcpy(ind.addr, nl_itr.get_data(), NAN_MAC_ADDR_LEN);
break;
case NAN_EVT_ATTR_FOLLOWUP_DW_OR_FAW:
ind.dw_or_faw = nl_itr.get_u8();
break;
case NAN_EVT_ATTR_FOLLOWUP_SERVICE_SPECIFIC_INFO_LEN:
ind.service_specific_info_len = nl_itr.get_u16();
break;
case NAN_EVT_ATTR_FOLLOWUP_SERVICE_SPECIFIC_INFO:
memcpy(ind.service_specific_info, nl_itr.get_data(), ind.service_specific_info_len);
break;
case NAN_EVT_ATTR_SDEA_LEN:
ind.sdea_service_specific_info_len = nl_itr.get_u16();
break;
case NAN_EVT_ATTR_SDEA:
memcpy(ind.sdea_service_specific_info, nl_itr.get_data(), ind.sdea_service_specific_info_len);
break;
default :
ALOGE("processNanDisabledEvent: unknown attribute(%d)", nl_itr.get_type());
return NL_SKIP;
}
}
if (callbackEventHandler.EventFollowup)
callbackEventHandler.EventFollowup(&ind);
return NL_OK;
}
int processNanDisabledEvent(WifiEvent &event) {
NanDisabledInd ind;
memset(&ind,0,sizeof(ind));
nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
for(nl_iterator nl_itr(vendor_data); nl_itr.has_next(); nl_itr.next()) {
switch(nl_itr.get_type()) {
case NAN_EVT_ATTR_DISABLED_REASON:
ind.reason = (NanStatusType)nl_itr.get_u32();
break;
default :
ALOGE("processNanDisabledEvent: unknown attribute(%d)", nl_itr.get_type());
return NL_SKIP;
}
}
if (callbackEventHandler.EventDisabled)
callbackEventHandler.EventDisabled(&ind);
return NL_OK;
}
int processNanDiscoveryEvent(WifiEvent &event) {
NanDiscEngEventInd ind;
memset(&ind,0,sizeof(ind));
u8 *addr = NULL;
nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
for(nl_iterator nl_itr(vendor_data); nl_itr.has_next(); nl_itr.next()) {
switch(nl_itr.get_type()) {
case NAN_EVT_ATTR_DISCOVERY_ENGINE_EVT_TYPE:
ind.event_type = (NanDiscEngEventType)nl_itr.get_u16();
break;
case NAN_EVT_ATTR_DISCOVERY_ENGINE_MAC_ADDR:
addr = (u8 *)nl_itr.get_data();
break;
default :
ALOGE("processNanDiscoveryEvent: unknown attribute(%d)", nl_itr.get_type());
return NL_SKIP;
}
}
if (addr) {
if (ind.event_type == NAN_EVENT_ID_DISC_MAC_ADDR)
memcpy(ind.data.mac_addr.addr, addr, NAN_MAC_ADDR_LEN);
else
memcpy(ind.data.cluster.addr, addr, NAN_MAC_ADDR_LEN);
} else {
ALOGE("processNanDiscoveryEvent: No Mac/cluster Address");
}
if (callbackEventHandler.EventDiscEngEvent)
callbackEventHandler.EventDiscEngEvent(&ind);
return NL_OK;
}
int processNanFollowupStatus(WifiEvent &event) {
NanTransmitFollowupInd ind;
memset(&ind,0,sizeof(ind));
ind.id = followupTid;
followupTid = 0;
nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
for(nl_iterator nl_itr(vendor_data); nl_itr.has_next(); nl_itr.next()) {
if (nl_itr.get_type() == NAN_EVT_ATTR_STATUS) {
ind.reason = (NanStatusType)nl_itr.get_u16();
} else {
ALOGE("processNanFollowupStatus: unknown attribute(%d)", nl_itr.get_type());
return NL_SKIP;
}
}
if (callbackEventHandler.EventTransmitFollowup)
callbackEventHandler.EventTransmitFollowup(&ind);
return NL_OK;
}
int putSdeaParams(NanSdeaCtrlParams *sdea_params, WifiRequest *request)
{
int result;
if (!sdea_params->config_nan_data_path)
return 0;
result = request->put_u8(NAN_REQ_ATTR_SDEA_PARAM_NDP_TYPE, sdea_params->ndp_type);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "enable:Failed to put SDEA PARAM ndp_type");
result = request->put_u8(NAN_REQ_ATTR_SDEA_PARAM_SECURITY_CFG, sdea_params->security_cfg);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "enable:Failed to put SDEA PARAM security_cfg");
result = request->put_u8(NAN_REQ_ATTR_SDEA_PARAM_RANGING_STATE, sdea_params->ranging_state);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "enable:Failed to put SDEA PARAM ranging_state");
result = request->put_u8(NAN_REQ_ATTR_SDEA_PARAM_RANGE_REPORT, sdea_params->range_report);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "enable:Failed to put SDEA PARAM range_report");
result = request->put_u8(NAN_REQ_ATTR_SDEA_PARAM_QOS_CFG, sdea_params->qos_cfg);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "enable:Failed to put SDEA PARAM qos_cfg");
return result;
}
int putRangingCfg(NanRangingCfg *ranging_cfg, WifiRequest *request)
{
int result;
result = request->put_u32(NAN_REQ_ATTR_RANGING_CFG_INTERVAL, ranging_cfg->ranging_interval_msec);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "enable:Failed to put Ranging CFG ranging_interval_msec");
result = request->put_u32(NAN_REQ_ATTR_RANGING_CFG_INDICATION, ranging_cfg->config_ranging_indications);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "enable:Failed to put Ranging CFG config_ranging_indications");
result = request->put_u32(NAN_REQ_ATTR_RANGING_CFG_INGRESS_MM, ranging_cfg->distance_ingress_mm);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "enable:Failed to put Ranging CFG distance_ingress_mm");
result = request->put_u32(NAN_REQ_ATTR_RANGING_CFG_EGRESS_MM, ranging_cfg->distance_egress_mm);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "enable:Failed to put Ranging CFG distance_egress_mm");
return result;
}
int putRangeResponseCfg(NanRangeResponseCfg *range_resp_cfg, WifiRequest *request)
{
int result;
result = request->put_u16(NAN_REQ_ATTR_RANGE_RESPONSE_CFG_PUBLISH_ID, range_resp_cfg->publish_id);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "Failed to put range response cfg::publish_id");
result = request->put_u32(NAN_REQ_ATTR_RANGE_RESPONSE_CFG_REQUESTOR_ID, range_resp_cfg->requestor_instance_id);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "Failed to put range response cfg::requestor_instance_id");
result = request->put_addr(NAN_REQ_ATTR_RANGE_RESPONSE_CFG_PEER_ADDR, range_resp_cfg->peer_addr);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "Failed to put range response cfg::peer_addr");
result = request->put_u16(NAN_REQ_ATTR_RANGE_RESPONSE_CFG_RANGING_RESPONSE, range_resp_cfg->ranging_response);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "Failed to put range response cfg::ranging_response");
return result;
}
int putSecurityInfo(u32 cipher, NanSecurityKeyInfo *key_info, u32 scid_len, u8 *scid, WifiRequest *request)
{
int result;
result = request->put_u32(NAN_REQ_ATTR_CIPHER_TYPE, cipher);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "enable:Failed to put cipher_type");
result = request->put_u32(NAN_REQ_ATTR_SECURITY_KEY_TYPE, key_info->key_type);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "enable:Failed to put cipher_type");
if (key_info->key_type == NAN_SECURITY_KEY_INPUT_PMK) {
result = request->put_u32(NAN_REQ_ATTR_SECURITY_PMK_LEN, key_info->body.pmk_info.pmk_len);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "enable:Failed to put key_info->body.pmk_info.pmk_len");
result = request->put(NAN_REQ_ATTR_SECURITY_PMK, key_info->body.pmk_info.pmk, key_info->body.pmk_info.pmk_len);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "enable:Failed to put key_info->body.pmk_info.pmk");
} else {
result = request->put_u32(NAN_REQ_ATTR_SECURITY_PASSPHRASE_LEN, key_info->body.passphrase_info.passphrase_len);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "enable:Failed to put key_info->body.passphrase_info.passphrase_len");
result = request->put(NAN_REQ_ATTR_SECURITY_PASSPHRASE, key_info->body.passphrase_info.passphrase,
key_info->body.passphrase_info.passphrase_len);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "enable:Failed to put key_info->body.passphrase_info.passphrase");
}
result = request->put_u32(NAN_REQ_ATTR_SCID_LEN, scid_len);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "enable:Failed to put scid_len");
if (scid_len) {
result = request->put(NAN_REQ_ATTR_SCID, scid, scid_len);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "enable:Failed to put scid");
}
return result;
}
public:
NanCommand(wifi_interface_handle iface, int id)
: WifiCommand(iface, id)
{
subscribeID[0] = 0;
subscribeID[1] = 0;
publishID[0] = 0;
publishID[1] = 0;
followupID[0] = 0;
followupID[1] = 0;
followupTid = 0;
publishTid = 0;
publishCancelTid = 0;
subscribeTid = 0;
subscribeCancelTid = 0;
enableTid = 0;
disableTid = 0;
configTid = 0;
capabilitiesTid = 0;
version = 0;
memset(&capabilities, 0, sizeof(capabilities));
}
int enable(transaction_id id, NanEnableRequest *msg) {
ALOGD("NAN enable id:%d", id);
WifiRequest request(familyId(), ifaceId());
int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_NAN_ENABLE);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "enable:Failed to create WifiRequest");
nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
if (!data) {
ALOGE("enable: request.attr_start fail");
return WIFI_ERROR_OUT_OF_MEMORY;
}
/* Valid master pref values are 2-254 */
int master_pref;
if (msg->master_pref < 2)
master_pref = 2;
else if (msg->master_pref > 254)
master_pref = 254;
else
master_pref = msg->master_pref;
result = request.put_u8(NAN_REQ_ATTR_MASTER_PREF, master_pref);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "enable:Failed to put master_pref");
result = request.put_u16(NAN_REQ_ATTR_CLUSTER_LOW, msg->cluster_low);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "enable:Failed to put cluster_low");
result = request.put_u16(NAN_REQ_ATTR_CLUSTER_HIGH, msg->cluster_high);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "enable:Failed to put cluster_high");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_support_5g, msg->support_5g_val,
NAN_REQ_ATTR_SUPPORT_5G_VAL, request, result, "enable:Failed to put support_5g_val");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_sid_beacon, msg->sid_beacon_val,
NAN_REQ_ATTR_SID_BEACON_VAL, request, result, "enable:Failed to put sid_beacon_val");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_2dot4g_rssi_close, msg->rssi_close_2dot4g_val,
NAN_REQ_ATTR_RSSI_CLOSE_2G4_VAL, request, result, "enable:Failed to put rssi_close_2dot4g_val");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_2dot4g_rssi_middle, msg->rssi_middle_2dot4g_val,
NAN_REQ_ATTR_RSSI_MIDDLE_2G4_VAL, request, result, "enable:Failed to put rssi_middle_2dot4g_val");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_2dot4g_rssi_proximity, msg->rssi_proximity_2dot4g_val,
NAN_REQ_ATTR_RSSI_PROXIMITY_2G4_VAL, request, result, "enable:Failed to put rssi_proximity_2dot4g_val");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_hop_count_limit, msg->hop_count_limit_val,
NAN_REQ_ATTR_HOP_COUNT_LIMIT_VAL, request, result, "enable:Failed to put hop_count_limit_val");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_2dot4g_support, msg->support_2dot4g_val,
NAN_REQ_ATTR_SUPPORT_2G4_VAL, request, result, "enable:Failed to put support_2dot4g_val");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_2dot4g_beacons, msg->beacon_2dot4g_val,
NAN_REQ_ATTR_BEACONS_2G4_VAL, request, result, "enable:Failed to put beacon_2dot4g_val");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_2dot4g_sdf, msg->sdf_2dot4g_val,
NAN_REQ_ATTR_SDF_2G4_VAL, request, result, "enable:Failed to put sdf_2dot4g_val");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_5g_beacons, msg->beacon_5g_val,
NAN_REQ_ATTR_BEACON_5G_VAL, request, result, "enable:Failed to put beacon_5g_val");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_5g_sdf, msg->sdf_5g_val,
NAN_REQ_ATTR_SDF_5G_VAL, request, result, "enable:Failed to put sdf_5g_val");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_5g_rssi_close, msg->rssi_close_5g_val,
NAN_REQ_ATTR_RSSI_CLOSE_5G_VAL, request, result, "enable:Failed to put rssi_close_5g_val");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_5g_rssi_middle, msg->rssi_middle_5g_val,
NAN_REQ_ATTR_RSSI_MIDDLE_5G_VAL, request, result, "enable:Failed to put rssi_middle_5g_val");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_5g_rssi_close_proximity, msg->rssi_close_proximity_5g_val,
NAN_REQ_ATTR_RSSI_CLOSE_PROXIMITY_5G_VAL, request, result, "enable:Failed to put rssi_close_proximity_5g_val");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_rssi_window_size, msg->rssi_window_size_val,
NAN_REQ_ATTR_RSSI_WINDOW_SIZE_VAL, request, result, "enable:Failed to put rssi_window_size_val");
CHECK_CONFIG_PUT_32_RETURN_FAIL(msg->config_oui, msg->oui_val,
NAN_REQ_ATTR_OUI_VAL, request, result, "enable:Failed to put oui_val");
CHECK_CONFIG_PUT_RETURN_FAIL(msg->config_intf_addr, msg->intf_addr_val, NAN_MAC_ADDR_LEN,
NAN_REQ_ATTR_MAC_ADDR_VAL, request, result, "enable:Failed to put intf_addr_val");
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, msg->config_cluster_attribute_val,
NAN_REQ_ATTR_CLUSTER_VAL, request, result, "enable:Failed to put config_cluster_attribute_val");
CHECK_CONFIG_PUT_RETURN_FAIL(msg->config_scan_params, msg->scan_params_val.dwell_time, sizeof(msg->scan_params_val.dwell_time),
NAN_REQ_ATTR_SOCIAL_CH_SCAN_DWELL_TIME, request, result, "enable:Failed to put scan_params_val.dwell_time");
CHECK_CONFIG_PUT_RETURN_FAIL(msg->config_scan_params, msg->scan_params_val.scan_period, sizeof(msg->scan_params_val.scan_period),
NAN_REQ_ATTR_SOCIAL_CH_SCAN_PERIOD, request, result, "enable:Failed to put scan_params_val.scan_period");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_random_factor_force, msg->random_factor_force_val,
NAN_REQ_ATTR_RANDOM_FACTOR_FORCE_VAL, request, result, "enable:Failed to put random_factor_force_val");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_hop_count_force, msg->hop_count_force_val,
NAN_REQ_ATTR_HOP_COUNT_FORCE_VAL, request, result, "enable:Failed to put hop_count_force_val");
CHECK_CONFIG_PUT_32_RETURN_FAIL(msg->config_24g_channel, msg->channel_24g_val,
NAN_REQ_ATTR_CHANNEL_2G4_MHZ_VAL, request, result, "enable:Failed to put channel_24g_val");
CHECK_CONFIG_PUT_32_RETURN_FAIL(msg->config_5g_channel, msg->channel_5g_val,
NAN_REQ_ATTR_CHANNEL_5G_MHZ_VAL, request, result, "enable:Failed to put channel_5g_val");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_subscribe_sid_beacon, msg->subscribe_sid_beacon_val,
NAN_REQ_ATTR_SUBSCRIBE_SID_BEACON_VAL, request, result, "enable:Failed to put subscribe_sid_beacon_val");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_dw.config_2dot4g_dw_band, msg->config_dw.dw_2dot4g_interval_val,
NAN_REQ_ATTR_DW_2G4_INTERVAL, request, result, "enable:Failed to put dw_2dot4g_interval_val");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_dw.config_5g_dw_band, msg->config_dw.dw_5g_interval_val,
NAN_REQ_ATTR_DW_5G_INTERVAL, request, result, "enable:Failed to put dw_5g_interval_val");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_disc_mac_addr_randomization, msg->disc_mac_addr_rand_interval_sec,
NAN_REQ_ATTR_DISC_MAC_ADDR_RANDOM_INTERVAL, request, result, "enable:Failed to put disc_mac_addr_rand_interval_sec");
request.attr_end(data);
registerNanEvents();
enableTid = id;
result = requestResponse(request);
if (result != WIFI_SUCCESS) {
enableTid = 0;
ALOGE("failed to NAN; result = %d", result);
unregisterNanEvents();
} else {
ALOGD("Start NAN...success");
}
return result;
}
int disable(transaction_id id)
{
ALOGD("NAN disable id:%d", id);
WifiRequest request(familyId(), ifaceId());
unregisterNanEvents();
int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_NAN_DISABLE);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "disable:Failed to create WifiRequest");
disableTid = id;
result = requestResponse(request);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "disable:Failed to requestResponse");
return result;
}
int config(transaction_id id, NanConfigRequest *msg) {
ALOGD("NAN config id:%d", id);
WifiRequest request(familyId(), ifaceId());
int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_NAN_CONFIG);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "config:Failed to create WifiRequest");
nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
if (!data) {
ALOGE("config: request.attr_start fail");
return WIFI_ERROR_OUT_OF_MEMORY;
}
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_sid_beacon, msg->sid_beacon,
NAN_REQ_ATTR_SID_BEACON_VAL, request, result, "config:Failed to put sid_beacon");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_rssi_proximity, msg->rssi_proximity,
NAN_REQ_ATTR_RSSI_PROXIMITY_2G4_VAL, request, result, "config:Failed to put rssi_proximity");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_master_pref, msg->master_pref,
NAN_REQ_ATTR_MASTER_PREF, request, result, "config:Failed to put master_pref");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_5g_rssi_close_proximity, msg->rssi_close_proximity_5g_val,
NAN_REQ_ATTR_RSSI_CLOSE_PROXIMITY_5G_VAL, request, result, "config:Failed to put rssi_close_proximity_5g_val");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_rssi_window_size, msg->rssi_window_size_val,
NAN_REQ_ATTR_RSSI_WINDOW_SIZE_VAL, request, result, "config:Failed to put rssi_window_size_val");
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, msg->config_cluster_attribute_val,
NAN_REQ_ATTR_CLUSTER_VAL, request, result, "config:Failed to put config_cluster_attribute_val");
CHECK_CONFIG_PUT_RETURN_FAIL(msg->config_scan_params, msg->scan_params_val.dwell_time, sizeof(msg->scan_params_val.dwell_time),
NAN_REQ_ATTR_SOCIAL_CH_SCAN_DWELL_TIME, request, result, "config:Failed to put scan_params_val.dwell_time");
CHECK_CONFIG_PUT_RETURN_FAIL(msg->config_scan_params, msg->scan_params_val.scan_period, sizeof(msg->scan_params_val.scan_period),
NAN_REQ_ATTR_SOCIAL_CH_SCAN_PERIOD, request, result, "config:Failed to put scan_params_val.scan_period");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_random_factor_force, msg->random_factor_force_val,
NAN_REQ_ATTR_RANDOM_FACTOR_FORCE_VAL, request, result, "config:Failed to put random_factor_force_val");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_hop_count_force, msg->hop_count_force_val,
NAN_REQ_ATTR_HOP_COUNT_FORCE_VAL, request, result, "config:Failed to put hop_count_force_val");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_conn_capability, msg->conn_capability_val.payload_transmit_flag,
NAN_REQ_ATTR_CONN_CAPABILITY_PAYLOAD_TX, request, result, "config:Failed to put payload_transmit_flag");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_conn_capability, msg->conn_capability_val.is_wfd_supported,
NAN_REQ_ATTR_CONN_CAPABILITY_WFD, request, result, "config:Failed to put is_wfd_supported");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_conn_capability, msg->conn_capability_val.is_wfds_supported,
NAN_REQ_ATTR_CONN_CAPABILITY_WFDS, request, result, "config:Failed to put is_wfds_supported");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_conn_capability, msg->conn_capability_val.is_tdls_supported,
NAN_REQ_ATTR_CONN_CAPABILITY_TDLS, request, result, "config:Failed to put is_tdls_supported");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_conn_capability, msg->conn_capability_val.is_ibss_supported,
NAN_REQ_ATTR_CONN_CAPABILITY_IBSS, request, result, "config:Failed to put is_ibss_supported");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_conn_capability, msg->conn_capability_val.is_mesh_supported,
NAN_REQ_ATTR_CONN_CAPABILITY_MESH, request, result, "config:Failed to put is_mesh_supported");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_conn_capability, msg->conn_capability_val.wlan_infra_field,
NAN_REQ_ATTR_CONN_CAPABILITY_WLAN_INFRA, request, result, "config:Failed to put wlan_infra_field");
if (msg->num_config_discovery_attr) {
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, msg->num_config_discovery_attr,
NAN_REQ_ATTR_DISCOVERY_ATTR_NUM_ENTRIES, request, result, "config:Failed to put msg->num_config_discovery_attr");
for (int i = 0; i < msg->num_config_discovery_attr; i++) {
nlattr *nl_disc_attribute = request.attr_start(NAN_REQ_ATTR_DISCOVERY_ATTR_VAL);
NanTransmitPostDiscovery *discovery_attr = &msg->discovery_attr_val[i];
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, discovery_attr->type,
NAN_REQ_ATTR_CONN_TYPE, request, result, "config:Failed to put discovery_attr->type");
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, discovery_attr->role,
NAN_REQ_ATTR_NAN_ROLE, request, result, "config:Failed to put discovery_attr->role");
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, discovery_attr->transmit_freq,
NAN_REQ_ATTR_TRANSMIT_FREQ, request, result, "config:Failed to put discovery_attr->transmit_freq");
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, discovery_attr->duration,
NAN_REQ_ATTR_AVAILABILITY_DURATION, request, result, "config:Failed to put discovery_attr->duration");
CHECK_CONFIG_PUT_32_RETURN_FAIL(1, discovery_attr->avail_interval_bitmap,
NAN_REQ_ATTR_AVAILABILITY_INTERVAL, request, result, "config:Failed to put discovery_attr->avail_interval_bitmap");
CHECK_CONFIG_PUT_RETURN_FAIL(1, discovery_attr->addr, NAN_MAC_ADDR_LEN,
NAN_REQ_ATTR_MAC_ADDR_VAL, request, result, "config:Failed to put discovery_attr->addr");
CHECK_CONFIG_PUT_16_RETURN_FAIL(1, discovery_attr->mesh_id_len,
NAN_REQ_ATTR_MESH_ID_LEN, request, result, "config:Failed to put discovery_attr->mesh_id");
CHECK_CONFIG_PUT_RETURN_FAIL(discovery_attr->mesh_id_len, discovery_attr->mesh_id, discovery_attr->mesh_id_len,
NAN_REQ_ATTR_MESH_ID, request, result, "config:Failed to put discovery_attr->mesh_id");
CHECK_CONFIG_PUT_16_RETURN_FAIL(1, discovery_attr->infrastructure_ssid_len,
NAN_REQ_ATTR_INFRASTRUCTURE_SSID_LEN, request, result, "config:Failed to put discovery_attr->infrastructure_ssid_val");
CHECK_CONFIG_PUT_RETURN_FAIL(discovery_attr->infrastructure_ssid_len, discovery_attr->infrastructure_ssid_val, discovery_attr->infrastructure_ssid_len,
NAN_REQ_ATTR_INFRASTRUCTURE_SSID, request, result, "config:Failed to put discovery_attr->infrastructure_ssid_val");
request.attr_end(nl_disc_attribute);
}
}
if (msg->config_fam) {
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, msg->fam_val.numchans,
NAN_REQ_ATTR_FURTHER_AVAIL_NUM_ENTRIES, request, result, "config:Failed to put msg->fam_val.numchans");
for (int i = 0; i < msg->fam_val.numchans; i++) {
nlattr *nl_fam_attribute = request.attr_start(NAN_REQ_ATTR_FURTHER_AVAIL_VAL);
NanFurtherAvailabilityChannel *further_avail_chan = &msg->fam_val.famchan[i];
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, further_avail_chan->entry_control,
NAN_REQ_ATTR_FURTHER_AVAIL_ENTRY_CTRL, request, result, "config:Failed to put further_avail_chan->entry_control");
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, further_avail_chan->class_val,
NAN_REQ_ATTR_FURTHER_AVAIL_CHAN_CLASS, request, result, "config:Failed to put further_avail_chan->class_val");
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, further_avail_chan->channel,
NAN_REQ_ATTR_FURTHER_AVAIL_CHAN, request, result, "config:Failed to put further_avail_chan->channel");
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, further_avail_chan->mapid,
NAN_REQ_ATTR_FURTHER_AVAIL_CHAN_MAPID, request, result, "config:Failed to put further_avail_chan->mapid");
CHECK_CONFIG_PUT_32_RETURN_FAIL(1, further_avail_chan->avail_interval_bitmap,
NAN_REQ_ATTR_FURTHER_AVAIL_INTERVAL_BITMAP, request, result, "config:Failed to put further_avail_chan->avail_interval_bitmap");
request.attr_end(nl_fam_attribute);
}
}
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_subscribe_sid_beacon, msg->subscribe_sid_beacon_val,
NAN_REQ_ATTR_SUBSCRIBE_SID_BEACON_VAL, request, result, "config:Failed to put subscribe_sid_beacon_val");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_dw.config_2dot4g_dw_band, msg->config_dw.dw_2dot4g_interval_val,
NAN_REQ_ATTR_DW_2G4_INTERVAL, request, result, "config:Failed to put dw_2dot4g_interval_val");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_dw.config_5g_dw_band, msg->config_dw.dw_5g_interval_val,
NAN_REQ_ATTR_DW_5G_INTERVAL, request, result, "config:Failed to put dw_5g_interval_val");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->config_disc_mac_addr_randomization, msg->disc_mac_addr_rand_interval_sec,
NAN_REQ_ATTR_DISC_MAC_ADDR_RANDOM_INTERVAL, request, result, "config:Failed to put disc_mac_addr_rand_interval_sec");
request.attr_end(data);
configTid = id;
result = requestResponse(request);
if (result != WIFI_SUCCESS) {
configTid = 0;
ALOGE("failed to set_config; result = %d", result);
} else {
ALOGD("NAN config...success");
}
return result;
}
static int setCallbackHandler(NanCallbackHandler handlers) {
callbackEventHandler = handlers;
return WIFI_SUCCESS;
}
static int getVersion(NanVersion *version) {
*version = SLSI_WIFI_HAL_NAN_VERSION;
return WIFI_SUCCESS;
}
int publish(transaction_id id, NanPublishRequest *msg) {
ALOGD("NAN publish transId:%d publishId:%d publishType:%d", id, msg->publish_id, msg->publish_type);
WifiRequest request(familyId(), ifaceId());
int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_NAN_PUBLISH);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "publish:Failed to create WifiRequest");
nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
if (!data) {
ALOGE("publish: request.attr_start fail");
return WIFI_ERROR_OUT_OF_MEMORY;
}
CHECK_CONFIG_PUT_16_RETURN_FAIL(msg->publish_id, msg->publish_id,
NAN_REQ_ATTR_PUBLISH_ID, request, result, "publish:Failed to put msg->publish_id");
CHECK_CONFIG_PUT_16_RETURN_FAIL(msg->ttl, msg->ttl,
NAN_REQ_ATTR_PUBLISH_TTL, request, result, "publish:Failed to put msg->ttl");
CHECK_CONFIG_PUT_16_RETURN_FAIL(1, msg->period,
NAN_REQ_ATTR_PUBLISH_PERIOD, request, result, "publish:Failed to put msg->period");
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, msg->publish_type,
NAN_REQ_ATTR_PUBLISH_TYPE, request, result, "publish:Failed to put msg->publish_type");
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, msg->tx_type,
NAN_REQ_ATTR_PUBLISH_TX_TYPE, request, result, "publish:Failed to put msg->tx_type");
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, msg->publish_count,
NAN_REQ_ATTR_PUBLISH_COUNT, request, result, "publish:Failed to put msg->publish_count");
CHECK_CONFIG_PUT_16_RETURN_FAIL(msg->service_name_len, msg->service_name_len,
NAN_REQ_ATTR_PUBLISH_SERVICE_NAME_LEN, request, result, "publish:Failed to put msg->service_name_len");
CHECK_CONFIG_PUT_RETURN_FAIL(msg->service_name_len, msg->service_name, msg->service_name_len,
NAN_REQ_ATTR_PUBLISH_SERVICE_NAME, request, result, "publish:Failed to put msg->service_name");
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, msg->publish_match_indicator,
NAN_REQ_ATTR_PUBLISH_MATCH_ALGO, request, result, "publish:Failed to put msg->publish_match_indicator");
CHECK_CONFIG_PUT_16_RETURN_FAIL(msg->service_specific_info_len, msg->service_specific_info_len,
NAN_REQ_ATTR_PUBLISH_SERVICE_INFO_LEN, request, result, "publish:Failed to put msg->service_specific_info_len");
CHECK_CONFIG_PUT_RETURN_FAIL(msg->service_specific_info_len, msg->service_specific_info, msg->service_specific_info_len,
NAN_REQ_ATTR_PUBLISH_SERVICE_INFO, request, result, "publish:Failed to put msg->service_specific_info");
CHECK_CONFIG_PUT_16_RETURN_FAIL(msg->rx_match_filter_len, msg->rx_match_filter_len,
NAN_REQ_ATTR_PUBLISH_RX_MATCH_FILTER_LEN, request, result, "publish:Failed to put msg->rx_match_filter_len");
CHECK_CONFIG_PUT_RETURN_FAIL(msg->rx_match_filter_len, msg->rx_match_filter, msg->rx_match_filter_len,
NAN_REQ_ATTR_PUBLISH_RX_MATCH_FILTER, request, result, "publish:Failed to put msg->rx_match_filter");
CHECK_CONFIG_PUT_16_RETURN_FAIL(msg->tx_match_filter_len, msg->tx_match_filter_len,
NAN_REQ_ATTR_PUBLISH_TX_MATCH_FILTER_LEN, request, result, "publish:Failed to put msg->tx_match_filter_len");
CHECK_CONFIG_PUT_RETURN_FAIL(msg->tx_match_filter_len, msg->tx_match_filter, msg->tx_match_filter_len,
NAN_REQ_ATTR_PUBLISH_TX_MATCH_FILTER, request, result, "publish:Failed to put msg->tx_match_filter");
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, msg->rssi_threshold_flag,
NAN_REQ_ATTR_PUBLISH_RSSI_THRESHOLD_FLAG, request, result, "publish:Failed to put msg->rssi_threshold_flag");
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, msg->connmap,
NAN_REQ_ATTR_PUBLISH_CONN_MAP, request, result, "publish:Failed to put msg->connmap");
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, msg->recv_indication_cfg,
NAN_REQ_ATTR_PUBLISH_RECV_IND_CFG, request, result, "publish:Failed to put msg->recv_indication_cfg");
CHECK_CONFIG_PUT_16_RETURN_FAIL(1, msg->sdea_service_specific_info_len,
NAN_REQ_ATTR_PUBLISH_SDEA_LEN, request, result, "publish:Failed to put msg->sdea_service_specific_info_len");
CHECK_CONFIG_PUT_RETURN_FAIL(msg->sdea_service_specific_info_len, msg->sdea_service_specific_info, msg->sdea_service_specific_info_len,
NAN_REQ_ATTR_PUBLISH_SDEA, request, result, "publish:Failed to put msg->sdea_service_specific_info");
result = request.put_u8(NAN_REQ_ATTR_RANGING_AUTO_RESPONSE, msg->ranging_auto_response);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "enable:Failed to put ranging_auto_response");
result = putSdeaParams(&msg->sdea_params, &request);
if (result != 0)
return result;
result = putRangingCfg(&msg->ranging_cfg, &request);
if (result != 0)
return result;
result = putSecurityInfo(msg->cipher_type, &msg->key_info, msg->scid_len, msg->scid, &request);
if (result != 0)
return result;
result = putRangeResponseCfg(&msg->range_response_cfg, &request);
if (result != 0)
return result;
request.attr_end(data);
publishTid = id;
result = requestResponse(request);
if (result != WIFI_SUCCESS) {
publishTid = 0;
ALOGE("failed to publish; result = %d", result);
} else {
ALOGD("NAN publish...success");
}
return result;
}
int publishCancel(transaction_id id, NanPublishCancelRequest *msg) {
ALOGD("NAN publishCancel transId:%d, publish_id:%d", id, msg->publish_id);
WifiRequest request(familyId(), ifaceId());
int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_NAN_PUBLISHCANCEL);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "publishCancel:Failed to create WifiRequest");
nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
if (!data) {
ALOGE("publishCancel: request.attr_start fail");
return WIFI_ERROR_OUT_OF_MEMORY;
}
CHECK_CONFIG_PUT_16_RETURN_FAIL(1, msg->publish_id,
NAN_REQ_ATTR_PUBLISH_ID, request, result, "publishCancel:Failed to put msg->publish_id");
request.attr_end(data);
publishCancelTid = id;
result = requestResponse(request);
if (result != WIFI_SUCCESS) {
publishCancelTid = 0;
ALOGE("failed to publishCancel; result = %d", result);
} else {
ALOGD("NAN publishCancel...success");
}
return result;
}
int subscribe(transaction_id id, NanSubscribeRequest *msg) {
ALOGD("NAN subscribe trans_id:%d subscribe_id:%d subscribetype:%d", id, msg->subscribe_id, msg->subscribe_type);
WifiRequest request(familyId(), ifaceId());
int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_NAN_SUBSCRIBE);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "subscribe:Failed to create WifiRequest");
nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
if (!data) {
ALOGE("subscribe: request.attr_start fail");
return WIFI_ERROR_OUT_OF_MEMORY;
}
CHECK_CONFIG_PUT_16_RETURN_FAIL(msg->subscribe_id, msg->subscribe_id,
NAN_REQ_ATTR_SUBSCRIBE_ID, request, result, "subscribe:Failed to put msg->publish_id");
CHECK_CONFIG_PUT_16_RETURN_FAIL(1, msg->ttl,
NAN_REQ_ATTR_SUBSCRIBE_TTL, request, result, "subscribe:Failed to put msg->ttl");
CHECK_CONFIG_PUT_16_RETURN_FAIL(1, msg->period,
NAN_REQ_ATTR_SUBSCRIBE_PERIOD, request, result, "subscribe:Failed to put msg->period");
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, msg->subscribe_type,
NAN_REQ_ATTR_SUBSCRIBE_TYPE, request, result, "subscribe:Failed to put msg->subscribe_type");
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, msg->serviceResponseFilter,
NAN_REQ_ATTR_SUBSCRIBE_RESP_FILTER_TYPE, request, result, "subscribe:Failed to put msg->serviceResponseFilter");
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, msg->serviceResponseInclude,
NAN_REQ_ATTR_SUBSCRIBE_RESP_INCLUDE, request, result, "subscribe:Failed to put msg->serviceResponseInclude");
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, msg->useServiceResponseFilter,
NAN_REQ_ATTR_SUBSCRIBE_USE_RESP_FILTER, request, result, "subscribe:Failed to put msg->useServiceResponseFilter");
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, msg->ssiRequiredForMatchIndication,
NAN_REQ_ATTR_SUBSCRIBE_SSI_REQUIRED, request, result, "subscribe:Failed to put msg->ssiRequiredForMatchIndication");
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, msg->subscribe_match_indicator,
NAN_REQ_ATTR_SUBSCRIBE_MATCH_INDICATOR, request, result, "subscribe:Failed to put msg->subscribe_match_indicator");
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, msg->subscribe_count,
NAN_REQ_ATTR_SUBSCRIBE_COUNT, request, result, "subscribe:Failed to put msg->subscribe_count");
CHECK_CONFIG_PUT_16_RETURN_FAIL(msg->service_name_len, msg->service_name_len,
NAN_REQ_ATTR_SUBSCRIBE_SERVICE_NAME_LEN, request, result, "subscribe:Failed to put msg->service_name_len");
CHECK_CONFIG_PUT_RETURN_FAIL(msg->service_name_len, msg->service_name, msg->service_name_len,
NAN_REQ_ATTR_SUBSCRIBE_SERVICE_NAME, request, result, "subscribe:Failed to put msg->service_name");
CHECK_CONFIG_PUT_16_RETURN_FAIL(msg->service_specific_info_len, msg->service_specific_info_len,
NAN_REQ_ATTR_SUBSCRIBE_SERVICE_INFO_LEN, request, result, "subscribe:Failed to put msg->service_specific_info_len");
CHECK_CONFIG_PUT_RETURN_FAIL(msg->service_specific_info_len, msg->service_specific_info, msg->service_specific_info_len,
NAN_REQ_ATTR_SUBSCRIBE_SERVICE_INFO, request, result, "subscribe:Failed to put msg->service_specific_info");
CHECK_CONFIG_PUT_16_RETURN_FAIL(msg->rx_match_filter_len, msg->rx_match_filter_len,
NAN_REQ_ATTR_SUBSCRIBE_RX_MATCH_FILTER_LEN, request, result, "subscribe:Failed to put msg->rx_match_filter_len");
CHECK_CONFIG_PUT_RETURN_FAIL(msg->rx_match_filter_len, msg->rx_match_filter, msg->rx_match_filter_len,
NAN_REQ_ATTR_SUBSCRIBE_RX_MATCH_FILTER, request, result, "subscribe:Failed to put msg->rx_match_filter");
CHECK_CONFIG_PUT_16_RETURN_FAIL(msg->tx_match_filter_len, msg->tx_match_filter_len,
NAN_REQ_ATTR_SUBSCRIBE_TX_MATCH_FILTER_LEN, request, result, "subscribe:Failed to put msg->tx_match_filter_len");
CHECK_CONFIG_PUT_RETURN_FAIL(msg->tx_match_filter_len, msg->tx_match_filter, msg->tx_match_filter_len,
NAN_REQ_ATTR_SUBSCRIBE_TX_MATCH_FILTER, request, result, "subscribe:Failed to put msg->tx_match_filter");
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, msg->rssi_threshold_flag,
NAN_REQ_ATTR_SUBSCRIBE_RSSI_THRESHOLD_FLAG, request, result, "subscribe:Failed to put msg->rssi_threshold_flag");
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, msg->connmap,
NAN_REQ_ATTR_SUBSCRIBE_CONN_MAP, request, result, "subscribe:Failed to put msg->connmap");
CHECK_CONFIG_PUT_8_RETURN_FAIL(msg->num_intf_addr_present, msg->num_intf_addr_present,
NAN_REQ_ATTR_SUBSCRIBE_NUM_INTF_ADDR_PRESENT, request, result, "subscribe:Failed to put msg->num_intf_addr_present");
CHECK_CONFIG_PUT_RETURN_FAIL(msg->num_intf_addr_present, msg->intf_addr, NAN_MAC_ADDR_LEN * msg->num_intf_addr_present,
NAN_REQ_ATTR_SUBSCRIBE_INTF_ADDR, request, result, "subscribe:Failed to put msg->intf_addr");
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, msg->recv_indication_cfg,
NAN_REQ_ATTR_SUBSCRIBE_RECV_IND_CFG, request, result, "subscribe:Failed to put msg->recv_indication_cfg");
CHECK_CONFIG_PUT_16_RETURN_FAIL(1, msg->sdea_service_specific_info_len,
NAN_REQ_ATTR_PUBLISH_SDEA_LEN, request, result, "subscribe:Failed to put msg->sdea_service_specific_info_len");
CHECK_CONFIG_PUT_RETURN_FAIL(msg->sdea_service_specific_info_len, msg->sdea_service_specific_info, msg->sdea_service_specific_info_len,
NAN_REQ_ATTR_PUBLISH_SDEA, request, result, "subscribe:Failed to put msg->sdea_service_specific_info");
result = request.put_u8(NAN_REQ_ATTR_RANGING_AUTO_RESPONSE, msg->ranging_auto_response);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "enable:Failed to put ranging_auto_response");
result = putSdeaParams(&msg->sdea_params, &request);
if (result != 0)
return result;
result = putRangingCfg(&msg->ranging_cfg, &request);
if (result != 0)
return result;
result = putSecurityInfo(msg->cipher_type, &msg->key_info, msg->scid_len, msg->scid, &request);
if (result != 0)
return result;
result = putRangeResponseCfg(&msg->range_response_cfg, &request);
if (result != 0)
return result;
request.attr_end(data);
subscribeTid = id;
result = requestResponse(request);
if (result != WIFI_SUCCESS) {
subscribeTid = 0;
ALOGE("failed to subscribe; result = %d", result);
} else {
ALOGD("NAN subscribe...success");
}
return result;
}
int subscribeCancel(transaction_id id, NanSubscribeCancelRequest *msg) {
ALOGD("NAN subscribeCancel transId:%d subscribeId:%d", id, msg->subscribe_id);
WifiRequest request(familyId(), ifaceId());
int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_NAN_SUBSCRIBECANCEL);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "subscribeCancel:Failed to create WifiRequest");
nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
if (!data) {
ALOGE("subscribeCancel: request.attr_start fail");
return WIFI_ERROR_OUT_OF_MEMORY;
}
CHECK_CONFIG_PUT_16_RETURN_FAIL(1, msg->subscribe_id,
NAN_REQ_ATTR_SUBSCRIBE_ID, request, result, "subscribeCancel:Failed to put msg->subscribe_id");
request.attr_end(data);
subscribeCancelTid = id;
result = requestResponse(request);
if (result != WIFI_SUCCESS) {
subscribeCancelTid = 0;
ALOGE("failed to subscribeCancel; result = %d", result);
} else {
ALOGD("NAN subscribeCancel...success");
}
return result;
}
int followup(transaction_id id, NanTransmitFollowupRequest *msg) {
ALOGD("NAN followup transid:%d pub/subId:%d reqInstId:%d", id, msg->publish_subscribe_id, msg->requestor_instance_id);
WifiRequest request(familyId(), ifaceId());
int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_NAN_TXFOLLOWUP);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "followup:Failed to create WifiRequest");
nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
if (!data) {
ALOGE("followup: request.attr_start fail");
return WIFI_ERROR_OUT_OF_MEMORY;
}
CHECK_CONFIG_PUT_16_RETURN_FAIL(1, msg->publish_subscribe_id,
NAN_REQ_ATTR_FOLLOWUP_ID, request, result, "followup:Failed to put msg->publish_subscribe_id");
CHECK_CONFIG_PUT_32_RETURN_FAIL(1, msg->requestor_instance_id,
NAN_REQ_ATTR_FOLLOWUP_REQUESTOR_ID, request, result, "followup:Failed to put msg->requestor_instance_id");
CHECK_CONFIG_PUT_RETURN_FAIL(1, msg->addr, NAN_MAC_ADDR_LEN,
NAN_REQ_ATTR_FOLLOWUP_ADDR, request, result, "followup:Failed to put msg->addr");
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, msg->priority,
NAN_REQ_ATTR_FOLLOWUP_PRIORITY, request, result, "followup:Failed to put msg->priority");
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, msg->dw_or_faw,
NAN_REQ_ATTR_FOLLOWUP_TX_WINDOW, request, result, "followup:Failed to put msg->dw_or_faw");
CHECK_CONFIG_PUT_16_RETURN_FAIL(msg->service_specific_info_len, msg->service_specific_info_len,
NAN_REQ_ATTR_FOLLOWUP_SERVICE_NAME_LEN, request, result, "followup:Failed to put msg->service_specific_info_len");
CHECK_CONFIG_PUT_RETURN_FAIL(msg->service_specific_info_len, msg->service_specific_info, msg->service_specific_info_len,
NAN_REQ_ATTR_FOLLOWUP_SERVICE_NAME, request, result, "followup:Failed to put msg->service_specific_info");
CHECK_CONFIG_PUT_8_RETURN_FAIL(1, msg->recv_indication_cfg,
NAN_REQ_ATTR_FOLLOWUP_RECV_IND_CFG, request, result, "followup:Failed to put msg->recv_indication_cfg");
CHECK_CONFIG_PUT_16_RETURN_FAIL(1, msg->sdea_service_specific_info_len,
NAN_REQ_ATTR_PUBLISH_SDEA_LEN, request, result, "publish:Failed to put msg->sdea_service_specific_info_len");
CHECK_CONFIG_PUT_RETURN_FAIL(msg->sdea_service_specific_info_len, msg->sdea_service_specific_info, msg->sdea_service_specific_info_len,
NAN_REQ_ATTR_PUBLISH_SDEA, request, result, "publish:Failed to put msg->sdea_service_specific_info");
request.attr_end(data);
followupTid = id;
result = requestResponse(request);
if (result != WIFI_SUCCESS) {
followupTid = 0;
ALOGE("failed to followup; result = %d", result);
} else {
ALOGD("NAN followup...success");
}
return result;
}
int getCapabilities(transaction_id id) {
ALOGD("NAN getCapabilities transId:%d", id);
WifiRequest request(familyId(), ifaceId());
int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_NAN_CAPABILITIES);
CHECK_WIFI_STATUS_RETURN_FAIL(result, "getCapabilities:Failed to create WifiRequest");
capabilitiesTid = id;
result = requestResponse(request);
if (result != WIFI_SUCCESS) {
capabilitiesTid = 0;
ALOGE("failed to getCapabilities; result = %d", result);
} else {
ALOGD("NAN getCapabilities...success");
}
return result;
}
int handleEvent(WifiEvent &event) {
int ret;
if (event.get_cmd() != NL80211_CMD_VENDOR) {
ALOGD("NAN %s Ignoring event with cmd = %d", __func__, event.get_cmd());
return NL_SKIP;
}
int id = event.get_vendor_id();
int subcmd = event.get_vendor_subcmd();
ALOGI("NAN %s Id = %0x, subcmd = %d", __func__, id, subcmd);
switch(subcmd) {
case SLSI_NAN_EVENT_MATCH:
ret = processMatchEvent(event);
break;
case SLSI_NAN_EVENT_MATCH_EXPIRED:
ret = processMatchExpiredEvent(event);
break;
case SLSI_NAN_EVENT_PUBLISH_TERMINATED:
ret = processPublishTerminatedEvent(event);
break;
case SLSI_NAN_EVENT_SUBSCRIBE_TERMINATED:
ret = processSubscribeTerminatedEvent(event);
break;
case SLSI_NAN_EVENT_FOLLOWUP:
ret = processFollowupEvent(event);
break;
case SLSI_NAN_EVENT_DISABLED:
ret = processNanDisabledEvent(event);
break;
case SLSI_NAN_EVENT_DISCOVERY_ENGINE:
ret = processNanDiscoveryEvent(event);
break;
case SLSI_NAN_EVENT_TRANSMIT_FOLLOWUP_STATUS:
ret = processNanFollowupStatus(event);
break;
}
return NL_OK;
}
int handleResponse(WifiEvent &reply) {
if (reply.get_cmd() != NL80211_CMD_VENDOR) {
ALOGD("NAN %s Ignoring reply with cmd = %d", __func__, reply.get_cmd());
return NL_SKIP;
}
NanResponseMsg response;
memset(&response, 0, sizeof(response));
if (processResponse(reply, &response) == NL_SKIP)
return NL_SKIP;
transaction_id id = 0;
switch ((int)response.response_type) {
case NAN_RESPONSE_PUBLISH:
id = publishTid;
publishTid = 0;
break;
case NAN_RESPONSE_ENABLED:
id = enableTid;
enableTid = 0;
break;
case NAN_RESPONSE_DISABLED:
id = disableTid;
disableTid = 0;
break;
case NAN_RESPONSE_PUBLISH_CANCEL:
id = publishCancelTid;
publishCancelTid = 0;
break;
case NAN_RESPONSE_SUBSCRIBE_CANCEL:
id = subscribeCancelTid;
subscribeCancelTid = 0;
break;
case NAN_RESPONSE_CONFIG:
id = configTid;
configTid = 0;
break;
case NAN_GET_CAPABILITIES:
id = capabilitiesTid;
capabilitiesTid = 0;
break;
case NAN_RESPONSE_SUBSCRIBE:
id = subscribeTid;
subscribeTid = 0;
break;
case NAN_RESPONSE_TRANSMIT_FOLLOWUP:
id = followupTid;
/* followupTid is required on receiving followup_up transmit status.
* Do not reset followupTid here*/
break;
}
ALOGD("NAN %s transId:%d status:%d, response:%d", __func__, id, response.status, response.response_type);
if (callbackEventHandler.NotifyResponse)
callbackEventHandler.NotifyResponse(id, &response);
return NL_OK;
}
};
NanCallbackHandler NanCommand::callbackEventHandler;
NanCommand *nan_get_object(transaction_id id,
wifi_interface_handle iface) {
wifi_handle handle = getWifiHandle(iface);
NanCommand *nanRequest = (NanCommand *)wifi_get_nan_cmd(handle);
if (!nanRequest) {
nanRequest = new NanCommand(iface, id);
if (!nanRequest){
ALOGE("Could not alloc NanCommand");
return NULL;
}
}
return nanRequest;
}
wifi_error nan_enable_request(transaction_id id,
wifi_interface_handle iface,
NanEnableRequest *msg) {
wifi_handle handle = getWifiHandle(iface);
wifi_error ret;
NanCommand *nanRequest = new NanCommand(iface, id);
if (!nanRequest) {
ALOGE("nan_enable_request:: Unable to create NanCommand");
return WIFI_ERROR_OUT_OF_MEMORY;
}
wifi_set_nan_cmd(handle, nanRequest);
ret = (wifi_error)nanRequest->enable(id, msg);
if (ret != WIFI_SUCCESS) {
wifi_reset_nan_cmd(handle);
delete nanRequest;
}
return ret;
}
/* Disable NAN functionality. */
wifi_error nan_disable_request(transaction_id id, wifi_interface_handle iface) {
NanCommand *nanRequest = nan_get_object(id, iface);
wifi_error ret;
if (!nanRequest) {
return WIFI_ERROR_OUT_OF_MEMORY;
}
ret = (wifi_error)nanRequest->disable(id);
wifi_reset_nan_cmd(getWifiHandle(iface));
delete nanRequest;
return ret;
}
/* Publish request to advertize a service. */
wifi_error nan_publish_request(transaction_id id,
wifi_interface_handle iface,
NanPublishRequest *msg) {
NanCommand *nanRequest = nan_get_object(id, iface);
if (!nanRequest) {
return WIFI_ERROR_OUT_OF_MEMORY;
}
return (wifi_error)nanRequest->publish(id, msg);
}
/* Cancel previous publish requests. */
wifi_error nan_publish_cancel_request(transaction_id id,
wifi_interface_handle iface,
NanPublishCancelRequest *msg) {
NanCommand *nanRequest = nan_get_object(id, iface);
if (!nanRequest) {
return WIFI_ERROR_OUT_OF_MEMORY;
}
return (wifi_error)nanRequest->publishCancel(id, msg);
}
/* Subscribe request to search for a service. */
wifi_error nan_subscribe_request(transaction_id id,
wifi_interface_handle iface,
NanSubscribeRequest *msg) {
NanCommand *nanRequest = nan_get_object(id, iface);
if (!nanRequest) {
return WIFI_ERROR_OUT_OF_MEMORY;
}
return (wifi_error)nanRequest->subscribe(id, msg);
}
/* Cancel previous subscribe requests. */
wifi_error nan_subscribe_cancel_request(transaction_id id,
wifi_interface_handle iface,
NanSubscribeCancelRequest *msg) {
NanCommand *nanRequest = nan_get_object(id, iface);
if (!nanRequest) {
return WIFI_ERROR_OUT_OF_MEMORY;
}
return (wifi_error)nanRequest->subscribeCancel(id, msg);
}
/* NAN transmit follow up request. */
wifi_error nan_transmit_followup_request(transaction_id id,
wifi_interface_handle iface,
NanTransmitFollowupRequest *msg) {
NanCommand *nanRequest = nan_get_object(id, iface);
if (!nanRequest) {
return WIFI_ERROR_OUT_OF_MEMORY;
}
return (wifi_error)nanRequest->followup(id, msg);
}
/* NAN configuration request. */
wifi_error nan_config_request(transaction_id id,
wifi_interface_handle iface,
NanConfigRequest *msg) {
NanCommand *nanRequest = nan_get_object(id, iface);
if (!nanRequest) {
return WIFI_ERROR_OUT_OF_MEMORY;
}
return (wifi_error)nanRequest->config(id, msg);
}
/* Register NAN callbacks. */
wifi_error nan_register_handler(wifi_interface_handle iface,
NanCallbackHandler handlers) {
return (wifi_error)NanCommand::setCallbackHandler(handlers);
}
/* Get NAN HAL version. */
wifi_error nan_get_version(wifi_handle handle,
NanVersion *version) {
return (wifi_error)NanCommand::getVersion(version);
}
/* Get NAN capabilities. */
wifi_error nan_get_capabilities(transaction_id id,
wifi_interface_handle iface) {
NanCommand *nanRequest = nan_get_object(id, iface);
if (!nanRequest) {
return WIFI_ERROR_OUT_OF_MEMORY;
}
return (wifi_error)nanRequest->getCapabilities(id);
}