Merge branch 'stage-aosp-master' into nyc-dev-plus-aosp

This commit is contained in:
The Android Automerger 2016-08-29 23:07:59 +00:00
commit f2e485fd79
6 changed files with 282 additions and 1049 deletions

View file

@ -1,7 +1,7 @@
# Copyright 2006 The Android Open Source Project # Copyright 2006 The Android Open Source Project
# Setting LOCAL_PATH will mess up all-subdir-makefiles, so do it beforehand. # Setting LOCAL_PATH will mess up all-subdir-makefiles, so do it beforehand.
legacy_modules := power uevent wifi legacy_modules := power uevent
SAVE_MAKEFILES := $(call all-named-subdir-makefiles,$(legacy_modules)) SAVE_MAKEFILES := $(call all-named-subdir-makefiles,$(legacy_modules))
LEGACY_AUDIO_MAKEFILES := $(call all-named-subdir-makefiles,audio) LEGACY_AUDIO_MAKEFILES := $(call all-named-subdir-makefiles,audio)
@ -22,6 +22,9 @@ LOCAL_SHARED_LIBRARIES += libdl
include $(SAVE_MAKEFILES) include $(SAVE_MAKEFILES)
# TODO: Remove this line b/29915755
LOCAL_WHOLE_STATIC_LIBRARIES := libwifi-hal-common
LOCAL_MODULE:= libhardware_legacy LOCAL_MODULE:= libhardware_legacy
include $(BUILD_SHARED_LIBRARY) include $(BUILD_SHARED_LIBRARY)

View file

@ -1,157 +0,0 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _WIFI_H
#define _WIFI_H
#if __cplusplus
extern "C" {
#endif
/**
* Load the Wi-Fi driver.
*
* @return 0 on success, < 0 on failure.
*/
int wifi_load_driver();
/**
* Unload the Wi-Fi driver.
*
* @return 0 on success, < 0 on failure.
*/
int wifi_unload_driver();
/**
* Check if the Wi-Fi driver is loaded.
* Check if the Wi-Fi driver is loaded.
* @return 0 on success, < 0 on failure.
*/
int is_wifi_driver_loaded();
/**
* Start supplicant.
*
* @return 0 on success, < 0 on failure.
*/
int wifi_start_supplicant(int p2pSupported);
/**
* Stop supplicant.
*
* @return 0 on success, < 0 on failure.
*/
int wifi_stop_supplicant(int p2pSupported);
/**
* Open a connection to supplicant
*
* @return 0 on success, < 0 on failure.
*/
int wifi_connect_to_supplicant();
/**
* Close connection to supplicant
*
* @return 0 on success, < 0 on failure.
*/
void wifi_close_supplicant_connection();
/**
* wifi_wait_for_event() performs a blocking call to
* get a Wi-Fi event and returns a string representing
* a Wi-Fi event when it occurs.
*
* @param buf is the buffer that receives the event
* @param len is the maximum length of the buffer
*
* @returns number of bytes in buffer, 0 if no
* event (for instance, no connection), and less than 0
* if there is an error.
*/
int wifi_wait_for_event(char *buf, size_t len);
/**
* wifi_command() issues a command to the Wi-Fi driver.
*
* Android extends the standard commands listed at
* /link http://hostap.epitest.fi/wpa_supplicant/devel/ctrl_iface_page.html
* to include support for sending commands to the driver:
*
* See wifi/java/android/net/wifi/WifiNative.java for the details of
* driver commands that are supported
*
* @param command is the string command (preallocated with 32 bytes)
* @param commandlen is command buffer length
* @param reply is a buffer to receive a reply string
* @param reply_len on entry, this is the maximum length of
* the reply buffer. On exit, the number of
* bytes in the reply buffer.
*
* @return 0 if successful, < 0 if an error.
*/
int wifi_command(const char *command, char *reply, size_t *reply_len);
/**
* do_dhcp_request() issues a dhcp request and returns the acquired
* information.
*
* All IPV4 addresses/mask are in network byte order.
*
* @param ipaddr return the assigned IPV4 address
* @param gateway return the gateway being used
* @param mask return the IPV4 mask
* @param dns1 return the IPV4 address of a DNS server
* @param dns2 return the IPV4 address of a DNS server
* @param server return the IPV4 address of DHCP server
* @param lease return the length of lease in seconds.
*
* @return 0 if successful, < 0 if error.
*/
int do_dhcp_request(int *ipaddr, int *gateway, int *mask,
int *dns1, int *dns2, int *server, int *lease);
/**
* Return the error string of the last do_dhcp_request().
*/
const char *get_dhcp_error_string();
/**
* Return the path to requested firmware
*/
#define WIFI_GET_FW_PATH_STA 0
#define WIFI_GET_FW_PATH_AP 1
#define WIFI_GET_FW_PATH_P2P 2
const char *wifi_get_fw_path(int fw_type);
/**
* Change the path to firmware for the wlan driver
*/
int wifi_change_fw_path(const char *fwpath);
/**
* Check and create if necessary initial entropy file
*/
#define WIFI_ENTROPY_FILE "/data/misc/wifi/entropy.bin"
int ensure_entropy_file_exists();
#if __cplusplus
}; // extern "C"
#endif
#endif // _WIFI_H

View file

@ -360,6 +360,21 @@ typedef struct {
NanVersion* version); NanVersion* version);
wifi_error (*wifi_nan_get_capabilities)(transaction_id id, wifi_error (*wifi_nan_get_capabilities)(transaction_id id,
wifi_interface_handle iface); wifi_interface_handle iface);
wifi_error (*wifi_nan_data_interface_create)(transaction_id id,
wifi_interface_handle iface,
char *iface_name);
wifi_error (*wifi_nan_data_interface_delete)(transaction_id id,
wifi_interface_handle iface,
char *iface_name);
wifi_error (*wifi_nan_data_request_initiator)(
transaction_id id, wifi_interface_handle iface,
NanDataPathInitiatorRequest *msg);
wifi_error (*wifi_nan_data_indication_response)(
transaction_id id, wifi_interface_handle iface,
NanDataPathIndicationResponse *msg);
wifi_error (*wifi_nan_data_end)(transaction_id id,
wifi_interface_handle iface,
NanDataPathEndRequest *msg);
/** /**
* Returns the chipset's hardware filtering capabilities: * Returns the chipset's hardware filtering capabilities:

View file

@ -17,6 +17,7 @@
#ifndef __NAN_H__ #ifndef __NAN_H__
#define __NAN_H__ #define __NAN_H__
#include <net/if.h>
#include "wifi_hal.h" #include "wifi_hal.h"
#ifdef __cplusplus #ifdef __cplusplus
@ -35,6 +36,7 @@ extern "C"
typedef int NanVersion; typedef int NanVersion;
typedef u16 transaction_id; typedef u16 transaction_id;
typedef u32 NanDataPathId;
#define NAN_MAC_ADDR_LEN 6 #define NAN_MAC_ADDR_LEN 6
#define NAN_MAJOR_VERSION 2 #define NAN_MAJOR_VERSION 2
@ -54,6 +56,7 @@ typedef u16 transaction_id;
#define NAN_MAX_FAM_CHANNELS 32 #define NAN_MAX_FAM_CHANNELS 32
#define NAN_MAX_POSTDISCOVERY_LEN 5 #define NAN_MAX_POSTDISCOVERY_LEN 5
#define NAN_MAX_FRAME_DATA_LEN 504 #define NAN_MAX_FRAME_DATA_LEN 504
#define NAN_DP_MAX_APP_INFO_LEN 512
/* /*
Definition of various NanResponseType Definition of various NanResponseType
@ -71,7 +74,12 @@ typedef enum {
NAN_RESPONSE_TCA = 9, NAN_RESPONSE_TCA = 9,
NAN_RESPONSE_ERROR = 10, NAN_RESPONSE_ERROR = 10,
NAN_RESPONSE_BEACON_SDF_PAYLOAD = 11, NAN_RESPONSE_BEACON_SDF_PAYLOAD = 11,
NAN_GET_CAPABILITIES = 12 NAN_GET_CAPABILITIES = 12,
NAN_DP_INTERFACE_CREATE = 13,
NAN_DP_INTERFACE_DELETE = 14,
NAN_DP_INITIATOR_RESPONSE = 15,
NAN_DP_RESPONDER_RESPONSE = 16,
NAN_DP_END = 17
} NanResponseType; } NanResponseType;
/* NAN Publish Types */ /* NAN Publish Types */
@ -139,7 +147,9 @@ typedef enum {
NAN_STATUS_NAN_NOT_ALLOWED = 22, NAN_STATUS_NAN_NOT_ALLOWED = 22,
NAN_STATUS_NO_OTA_ACK = 23, NAN_STATUS_NO_OTA_ACK = 23,
NAN_STATUS_TX_FAIL = 24, NAN_STATUS_TX_FAIL = 24,
/* 25-4095 Reserved */ NAN_STATUS_ALREADY_ENABLED = 25,
NAN_STATUS_FOLLOWUP_QUEUE_FULL = 26,
/* 27-4095 Reserved */
/* NAN Configuration Response codes */ /* NAN Configuration Response codes */
NAN_STATUS_INVALID_RSSI_CLOSE_VALUE = 4096, NAN_STATUS_INVALID_RSSI_CLOSE_VALUE = 4096,
NAN_STATUS_INVALID_RSSI_MIDDLE_VALUE = 4097, NAN_STATUS_INVALID_RSSI_MIDDLE_VALUE = 4097,
@ -177,7 +187,26 @@ typedef enum {
NAN_TERMINATED_REASON_DISABLE_IN_PROGRESS = 8198, NAN_TERMINATED_REASON_DISABLE_IN_PROGRESS = 8198,
NAN_TERMINATED_REASON_POST_DISC_ATTR_EXPIRED = 8199, NAN_TERMINATED_REASON_POST_DISC_ATTR_EXPIRED = 8199,
NAN_TERMINATED_REASON_POST_DISC_LEN_EXCEEDED = 8200, NAN_TERMINATED_REASON_POST_DISC_LEN_EXCEEDED = 8200,
NAN_TERMINATED_REASON_FURTHER_AVAIL_MAP_EMPTY = 8201 NAN_TERMINATED_REASON_FURTHER_AVAIL_MAP_EMPTY = 8201,
/* 9000-9500 NDP Status type */
NDP_UNSUPPORTED_CONCURRENCY = 9000,
NDP_NAN_DATA_IFACE_CREATE_FAILED = 9001,
NDP_NAN_DATA_IFACE_DELETE_FAILED = 9002,
NDP_DATA_INITIATOR_REQUEST_FAILED = 9003,
NDP_DATA_RESPONDER_REQUEST_FAILED = 9004,
NDP_INVALID_SERVICE_INSTANCE_ID = 9005,
NDP_INVALID_NDP_INSTANCE_ID = 9006,
NDP_INVALID_RESPONSE_CODE = 9007,
NDP_INVALID_APP_INFO_LEN = 9008,
/* OTA failures and timeouts during negotiation */
NDP_MGMT_FRAME_REQUEST_FAILED = 9009,
NDP_MGMT_FRAME_RESPONSE_FAILED = 9010,
NDP_MGMT_FRAME_CONFIRM_FAILED = 9011,
NDP_END_FAILED = 9012,
NDP_MGMT_FRAME_END_REQUEST_FAILED = 9013,
/* 9500 onwards vendor specific error codes */
NDP_VENDOR_SPECIFIC_ERROR = 9500
} NanStatusType; } NanStatusType;
/* NAN Transmit Types */ /* NAN Transmit Types */
@ -219,8 +248,8 @@ typedef enum {
/* NAN SRF State in Subscribe */ /* NAN SRF State in Subscribe */
typedef enum { typedef enum {
NAN_USE_SRF = 0, NAN_DO_NOT_USE_SRF = 0,
NAN_DO_NOT_USE_SRF NAN_USE_SRF
} NanSRFState; } NanSRFState;
/* NAN Include SSI in MatchInd */ /* NAN Include SSI in MatchInd */
@ -229,6 +258,25 @@ typedef enum {
NAN_SSI_REQUIRED_IN_MATCH_IND NAN_SSI_REQUIRED_IN_MATCH_IND
} NanSsiInMatchInd; } NanSsiInMatchInd;
/* NAN DP security Configuration */
typedef enum {
NAN_DP_CONFIG_NO_SECURITY = 0,
NAN_DP_CONFIG_SECURITY
} NanDataPathSecurityCfgStatus;
/* Data request Responder's response */
typedef enum {
NAN_DP_REQUEST_ACCEPT = 0,
NAN_DP_REQUEST_REJECT
} NanDataPathResponseCode;
/* NAN DP channel config options */
typedef enum {
NAN_DP_CHANNEL_NOT_REQUESTED = 0,
NAN_DP_REQUEST_CHANNEL_SETUP,
NAN_DP_FORCE_CHANNEL_SETUP
} NanDataPathChannelCfg;
/* Nan/NDP Capabilites info */ /* Nan/NDP Capabilites info */
typedef struct { typedef struct {
u32 max_concurrent_nan_clusters; u32 max_concurrent_nan_clusters;
@ -243,6 +291,7 @@ typedef struct {
u32 max_ndi_interfaces; u32 max_ndi_interfaces;
u32 max_ndp_sessions; u32 max_ndp_sessions;
u32 max_app_info_len; u32 max_app_info_len;
u32 max_queued_transmit_followup_msgs;
} NanCapabilities; } NanCapabilities;
/* /*
@ -698,7 +747,7 @@ typedef struct {
u8 rssi_close_proximity_5g_val; u8 rssi_close_proximity_5g_val;
/* /*
1 byte quantity which defines the window size over 1 byte quantity which defines the window size over
which the average RSSI will be calculated over. which the average RSSI will be calculated over.
*/ */
u8 config_rssi_window_size; u8 config_rssi_window_size;
u8 rssi_window_size_val; u8 rssi_window_size_val;
@ -720,7 +769,7 @@ typedef struct {
*/ */
u8 config_cluster_attribute_val; u8 config_cluster_attribute_val;
/* /*
The periodicity in seconds between full scans to find any new The periodicity in seconds between full scans to find any new
clusters available in the area. A Full scan should not be done clusters available in the area. A Full scan should not be done
more than every 10 seconds and should not be done less than every more than every 10 seconds and should not be done less than every
30 seconds. 30 seconds.
@ -797,9 +846,9 @@ typedef struct {
/* /*
flag which specifies that the Publish should use the configured RSSI flag which specifies that the Publish should use the configured RSSI
threshold and the received RSSI in order to filter requests threshold and the received RSSI in order to filter requests
0 ignore the configured RSSI threshold when running a Service 0 ignore the configured RSSI threshold when running a Service
Descriptor attribute or Service ID List Attribute through the DE matching logic. Descriptor attribute or Service ID List Attribute through the DE matching logic.
1 use the configured RSSI threshold when running a Service 1 use the configured RSSI threshold when running a Service
Descriptor attribute or Service ID List Attribute through the DE matching logic. Descriptor attribute or Service ID List Attribute through the DE matching logic.
*/ */
@ -903,9 +952,9 @@ typedef struct {
/* /*
Flag which specifies that the Subscribe should use the configured RSSI Flag which specifies that the Subscribe should use the configured RSSI
threshold and the received RSSI in order to filter requests threshold and the received RSSI in order to filter requests
0 ignore the configured RSSI threshold when running a Service 0 ignore the configured RSSI threshold when running a Service
Descriptor attribute or Service ID List Attribute through the DE matching logic. Descriptor attribute or Service ID List Attribute through the DE matching logic.
1 use the configured RSSI threshold when running a Service 1 use the configured RSSI threshold when running a Service
Descriptor attribute or Service ID List Attribute through the DE matching logic. Descriptor attribute or Service ID List Attribute through the DE matching logic.
*/ */
@ -1016,7 +1065,7 @@ typedef struct {
*/ */
/* /*
2 byte quantity which defines the window size over 2 byte quantity which defines the window size over
which the average RSSI will be calculated over. which the average RSSI will be calculated over.
*/ */
u8 config_rssi_window_size; u8 config_rssi_window_size;
u16 rssi_window_size_val; u16 rssi_window_size_val;
@ -1027,7 +1076,7 @@ typedef struct {
*/ */
u8 config_cluster_attribute_val; u8 config_cluster_attribute_val;
/* /*
The periodicity in seconds between full scans to find any new The periodicity in seconds between full scans to find any new
clusters available in the area. A Full scan should not be done clusters available in the area. A Full scan should not be done
more than every 10 seconds and should not be done less than every more than every 10 seconds and should not be done less than every
30 seconds. 30 seconds.
@ -1301,6 +1350,15 @@ typedef struct {
} data; } data;
} NanStatsResponse; } NanStatsResponse;
/* Response returned for Initiators Data request */
typedef struct {
/*
Unique token Id generated on the initiator
side used for a NDP session between two NAN devices
*/
NanDataPathId ndp_instance_id;
} NanDataPathRequestResponse;
/* /*
NAN Response messages NAN Response messages
*/ */
@ -1312,6 +1370,7 @@ typedef struct {
NanPublishResponse publish_response; NanPublishResponse publish_response;
NanSubscribeResponse subscribe_response; NanSubscribeResponse subscribe_response;
NanStatsResponse stats_response; NanStatsResponse stats_response;
NanDataPathRequestResponse data_request_response;
NanCapabilities nan_capabilities; NanCapabilities nan_capabilities;
} body; } body;
} NanResponseMsg; } NanResponseMsg;
@ -1562,6 +1621,162 @@ typedef struct {
NanBeaconSdfPayloadReceive data; NanBeaconSdfPayloadReceive data;
} NanBeaconSdfPayloadInd; } NanBeaconSdfPayloadInd;
/*
Event Indication notifying the
transmit followup in progress
*/
typedef struct {
transaction_id id;
NanStatusType reason;
} NanTransmitFollowupInd;
/*
Data request Initiator/Responder
app/service related info
*/
typedef struct {
u16 ndp_app_info_len;
u8 ndp_app_info[NAN_DP_MAX_APP_INFO_LEN];
} NanDataPathAppInfo;
/* QoS configuration */
typedef enum {
NAN_DP_CONFIG_NO_QOS = 0,
NAN_DP_CONFIG_QOS
} NanDataPathQosCfg;
/* Configuration params of Data request Initiator/Responder */
typedef struct {
/* Status Indicating Security/No Security */
NanDataPathSecurityCfgStatus security_cfg;
NanDataPathQosCfg qos_cfg;
} NanDataPathCfg;
/* Nan Data Path Initiator requesting a data session */
typedef struct {
/*
Unique Instance Id identifying the Responder's service.
This is same as publish_id notified on the subscribe side
in a publish/subscribe scenario
*/
u32 service_instance_id; /* Value 0 for no publish/subscribe */
/* Config flag for channel request */
NanDataPathChannelCfg channel_request_type;
/* Channel frequency in MHz to start data-path */
wifi_channel channel;
/*
Discovery MAC addr of the publisher/peer
*/
u8 peer_disc_mac_addr[NAN_MAC_ADDR_LEN];
/*
Interface name on which this NDP session is to be started.
This will be the same interface name provided during interface
create.
*/
char ndp_iface[IFNAMSIZ+1];
/* Initiator/Responder Security/QoS configuration */
NanDataPathCfg ndp_cfg;
/* App/Service information of the Initiator */
NanDataPathAppInfo app_info;
} NanDataPathInitiatorRequest;
/*
Data struct to initiate a data response on the responder side
for an indication received with a data request
*/
typedef struct {
/*
Unique token Id generated on the initiator/responder
side used for a NDP session between two NAN devices
*/
NanDataPathId ndp_instance_id;
/*
Interface name on which this NDP session is to be started.
This will be the same interface name provided during interface
create.
*/
char ndp_iface[IFNAMSIZ+1];
/* Initiator/Responder Security/QoS configuration */
NanDataPathCfg ndp_cfg;
/* App/Service information of the responder */
NanDataPathAppInfo app_info;
/* Response Code indicating ACCEPT/REJECT/DEFER */
NanDataPathResponseCode rsp_code;
} NanDataPathIndicationResponse;
/* NDP termination info */
typedef struct {
u8 num_ndp_instances;
/*
Unique token Id generated on the initiator/responder side
used for a NDP session between two NAN devices
*/
NanDataPathId ndp_instance_id[];
} NanDataPathEndRequest;
/*
Event indication received on the
responder side when a Nan Data request or
NDP session is initiated on the Initiator side
*/
typedef struct {
/*
Unique Instance Id corresponding to a service/session.
This is similar to the publish_id generated on the
publisher side
*/
u16 service_instance_id;
/* Discovery MAC addr of the peer/initiator */
u8 peer_disc_mac_addr[NAN_MAC_ADDR_LEN];
/*
Unique token Id generated on the initiator/responder side
used for a NDP session between two NAN devices
*/
NanDataPathId ndp_instance_id;
/* Initiator/Responder Security/QoS configuration */
NanDataPathCfg ndp_cfg;
/* App/Service information of the initiator */
NanDataPathAppInfo app_info;
} NanDataPathRequestInd;
/*
Event indication of data confirm is received on both
initiator and responder side confirming a NDP session
*/
typedef struct {
/*
Unique token Id generated on the initiator/responder side
used for a NDP session between two NAN devices
*/
NanDataPathId ndp_instance_id;
/*
NDI mac address of the peer
(required to derive target ipv6 address)
*/
u8 peer_ndi_mac_addr[NAN_MAC_ADDR_LEN];
/* App/Service information of Initiator/Responder */
NanDataPathAppInfo app_info;
/* Response code indicating ACCEPT/REJECT/DEFER */
NanDataPathResponseCode rsp_code;
/* Reason code indicating the cause for REJECT */
NanStatusType reason_code;
} NanDataPathConfirmInd;
/*
Event indication received on the
initiator/responder side terminating
a NDP session
*/
typedef struct {
u8 num_ndp_instances;
/*
Unique token Id generated on the initiator/responder side
used for a NDP session between two NAN devices
*/
NanDataPathId ndp_instance_id[];
} NanDataPathEndInd;
/* Response and Event Callbacks */ /* Response and Event Callbacks */
typedef struct { typedef struct {
/* NotifyResponse invoked to notify the status of the Request */ /* NotifyResponse invoked to notify the status of the Request */
@ -1576,6 +1791,10 @@ typedef struct {
void (*EventDisabled) (NanDisabledInd* event); void (*EventDisabled) (NanDisabledInd* event);
void (*EventTca) (NanTCAInd* event); void (*EventTca) (NanTCAInd* event);
void (*EventBeaconSdfPayload) (NanBeaconSdfPayloadInd* event); void (*EventBeaconSdfPayload) (NanBeaconSdfPayloadInd* event);
void (*EventDataRequest)(NanDataPathRequestInd* event);
void (*EventDataConfirm)(NanDataPathConfirmInd* event);
void (*EventDataEnd)(NanDataPathEndInd* event);
void (*EventTransmitFollowup) (NanTransmitFollowupInd* event);
} NanCallbackHandler; } NanCallbackHandler;
/* Enable NAN functionality. */ /* Enable NAN functionality. */
@ -1648,6 +1867,37 @@ wifi_error nan_get_version(wifi_handle handle,
/* Get NAN capabilities. */ /* Get NAN capabilities. */
wifi_error nan_get_capabilities(transaction_id id, wifi_error nan_get_capabilities(transaction_id id,
wifi_interface_handle iface); wifi_interface_handle iface);
/* ========== Nan Data Path APIs ================ */
/* Create NAN Data Interface */
wifi_error nan_data_interface_create(transaction_id id,
wifi_interface_handle iface,
char* iface_name);
/* Delete NAN Data Interface */
wifi_error nan_data_interface_delete(transaction_id id,
wifi_interface_handle iface,
char* iface_name);
/* Initiate a NDP session: Initiator */
wifi_error nan_data_request_initiator(transaction_id id,
wifi_interface_handle iface,
NanDataPathInitiatorRequest* msg);
/*
Response to a data indication received
corresponding to a NDP session. An indication
is received with a data request and the responder
will send a data response
*/
wifi_error nan_data_indication_response(transaction_id id,
wifi_interface_handle iface,
NanDataPathIndicationResponse* msg);
/* NDL termination request: from either Initiator/Responder */
wifi_error nan_data_end(transaction_id id,
wifi_interface_handle iface,
NanDataPathEndRequest* msg);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */

View file

@ -1,44 +0,0 @@
# Copyright 2006 The Android Open Source Project
ifdef WIFI_DRIVER_MODULE_PATH
LOCAL_CFLAGS += -DWIFI_DRIVER_MODULE_PATH=\"$(WIFI_DRIVER_MODULE_PATH)\"
endif
ifdef WIFI_DRIVER_MODULE_ARG
LOCAL_CFLAGS += -DWIFI_DRIVER_MODULE_ARG=\"$(WIFI_DRIVER_MODULE_ARG)\"
endif
ifdef WIFI_DRIVER_MODULE_NAME
LOCAL_CFLAGS += -DWIFI_DRIVER_MODULE_NAME=\"$(WIFI_DRIVER_MODULE_NAME)\"
endif
ifdef WIFI_FIRMWARE_LOADER
LOCAL_CFLAGS += -DWIFI_FIRMWARE_LOADER=\"$(WIFI_FIRMWARE_LOADER)\"
endif
ifdef WIFI_DRIVER_FW_PATH_STA
LOCAL_CFLAGS += -DWIFI_DRIVER_FW_PATH_STA=\"$(WIFI_DRIVER_FW_PATH_STA)\"
endif
ifdef WIFI_DRIVER_FW_PATH_AP
LOCAL_CFLAGS += -DWIFI_DRIVER_FW_PATH_AP=\"$(WIFI_DRIVER_FW_PATH_AP)\"
endif
ifdef WIFI_DRIVER_FW_PATH_P2P
LOCAL_CFLAGS += -DWIFI_DRIVER_FW_PATH_P2P=\"$(WIFI_DRIVER_FW_PATH_P2P)\"
endif
ifdef WIFI_DRIVER_FW_PATH_PARAM
LOCAL_CFLAGS += -DWIFI_DRIVER_FW_PATH_PARAM=\"$(WIFI_DRIVER_FW_PATH_PARAM)\"
endif
ifdef WIFI_DRIVER_STATE_CTRL_PARAM
LOCAL_CFLAGS += -DWIFI_DRIVER_STATE_CTRL_PARAM=\"$(WIFI_DRIVER_STATE_CTRL_PARAM)\"
endif
ifdef WIFI_DRIVER_STATE_ON
LOCAL_CFLAGS += -DWIFI_DRIVER_STATE_ON=\"$(WIFI_DRIVER_STATE_ON)\"
endif
ifdef WIFI_DRIVER_STATE_OFF
LOCAL_CFLAGS += -DWIFI_DRIVER_STATE_OFF=\"$(WIFI_DRIVER_STATE_OFF)\"
endif
LOCAL_SRC_FILES += wifi/wifi.c
ifdef WPA_SUPPLICANT_VERSION
LOCAL_CFLAGS += -DLIBWPA_CLIENT_EXISTS
LOCAL_SHARED_LIBRARIES += libwpa_client
endif
LOCAL_SHARED_LIBRARIES += libnetutils

View file

@ -1,834 +0,0 @@
/*
* Copyright 2008, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <dirent.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <unistd.h>
#include <poll.h>
#include "hardware_legacy/wifi.h"
#ifdef LIBWPA_CLIENT_EXISTS
#include "libwpa_client/wpa_ctrl.h"
#endif
#define LOG_TAG "WifiHW"
#include "cutils/log.h"
#include "cutils/memory.h"
#include "cutils/misc.h"
#include "cutils/properties.h"
#include "private/android_filesystem_config.h"
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
#include <sys/_system_properties.h>
extern int do_dhcp();
extern int ifc_init();
extern void ifc_close();
extern char *dhcp_lasterror();
extern void get_dhcp_info();
extern int init_module(void *, unsigned long, const char *);
extern int delete_module(const char *, unsigned int);
void wifi_close_sockets();
#ifndef LIBWPA_CLIENT_EXISTS
#define WPA_EVENT_TERMINATING "CTRL-EVENT-TERMINATING "
struct wpa_ctrl {};
void wpa_ctrl_cleanup(void) {}
struct wpa_ctrl *wpa_ctrl_open(const char *ctrl_path) { return NULL; }
void wpa_ctrl_close(struct wpa_ctrl *ctrl) {}
int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
char *reply, size_t *reply_len, void (*msg_cb)(char *msg, size_t len))
{ return 0; }
int wpa_ctrl_attach(struct wpa_ctrl *ctrl) { return 0; }
int wpa_ctrl_detach(struct wpa_ctrl *ctrl) { return 0; }
int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
{ return 0; }
int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl) { return 0; }
#endif
static struct wpa_ctrl *ctrl_conn;
static struct wpa_ctrl *monitor_conn;
/* socket pair used to exit from a blocking read */
static int exit_sockets[2];
static char primary_iface[PROPERTY_VALUE_MAX];
// TODO: use new ANDROID_SOCKET mechanism, once support for multiple
// sockets is in
#ifndef WIFI_DRIVER_MODULE_ARG
#define WIFI_DRIVER_MODULE_ARG ""
#endif
#ifndef WIFI_FIRMWARE_LOADER
#define WIFI_FIRMWARE_LOADER ""
#endif
#define WIFI_TEST_INTERFACE "sta"
#ifndef WIFI_DRIVER_FW_PATH_STA
#define WIFI_DRIVER_FW_PATH_STA NULL
#endif
#ifndef WIFI_DRIVER_FW_PATH_AP
#define WIFI_DRIVER_FW_PATH_AP NULL
#endif
#ifndef WIFI_DRIVER_FW_PATH_P2P
#define WIFI_DRIVER_FW_PATH_P2P NULL
#endif
#ifndef WIFI_DRIVER_FW_PATH_PARAM
#define WIFI_DRIVER_FW_PATH_PARAM "/sys/module/wlan/parameters/fwpath"
#endif
#define WIFI_DRIVER_LOADER_DELAY 1000000
static const char IFACE_DIR[] = "/data/system/wpa_supplicant";
#ifdef WIFI_DRIVER_MODULE_PATH
static const char DRIVER_MODULE_NAME[] = WIFI_DRIVER_MODULE_NAME;
static const char DRIVER_MODULE_TAG[] = WIFI_DRIVER_MODULE_NAME " ";
static const char DRIVER_MODULE_PATH[] = WIFI_DRIVER_MODULE_PATH;
static const char DRIVER_MODULE_ARG[] = WIFI_DRIVER_MODULE_ARG;
#endif
static const char FIRMWARE_LOADER[] = WIFI_FIRMWARE_LOADER;
static const char DRIVER_PROP_NAME[] = "wlan.driver.status";
static const char SUPPLICANT_NAME[] = "wpa_supplicant";
static const char SUPP_PROP_NAME[] = "init.svc.wpa_supplicant";
static const char P2P_SUPPLICANT_NAME[] = "p2p_supplicant";
static const char P2P_PROP_NAME[] = "init.svc.p2p_supplicant";
static const char SUPP_CONFIG_TEMPLATE[]= "/system/etc/wifi/wpa_supplicant.conf";
static const char SUPP_CONFIG_FILE[] = "/data/misc/wifi/wpa_supplicant.conf";
static const char P2P_CONFIG_FILE[] = "/data/misc/wifi/p2p_supplicant.conf";
static const char CONTROL_IFACE_PATH[] = "/data/misc/wifi/sockets";
static const char MODULE_FILE[] = "/proc/modules";
static const char IFNAME[] = "IFNAME=";
#define IFNAMELEN (sizeof(IFNAME) - 1)
static const char WPA_EVENT_IGNORE[] = "CTRL-EVENT-IGNORE ";
static const char SUPP_ENTROPY_FILE[] = WIFI_ENTROPY_FILE;
static unsigned char dummy_key[21] = { 0x02, 0x11, 0xbe, 0x33, 0x43, 0x35,
0x68, 0x47, 0x84, 0x99, 0xa9, 0x2b,
0x1c, 0xd3, 0xee, 0xff, 0xf1, 0xe2,
0xf3, 0xf4, 0xf5 };
/* Is either SUPPLICANT_NAME or P2P_SUPPLICANT_NAME */
static char supplicant_name[PROPERTY_VALUE_MAX];
/* Is either SUPP_PROP_NAME or P2P_PROP_NAME */
static char supplicant_prop_name[PROPERTY_KEY_MAX];
static int insmod(const char *filename, const char *args)
{
void *module;
unsigned int size;
int ret;
module = load_file(filename, &size);
if (!module)
return -1;
ret = init_module(module, size, args);
free(module);
return ret;
}
static int rmmod(const char *modname)
{
int ret = -1;
int maxtry = 10;
while (maxtry-- > 0) {
ret = delete_module(modname, O_NONBLOCK | O_EXCL);
if (ret < 0 && errno == EAGAIN)
usleep(500000);
else
break;
}
if (ret != 0)
ALOGD("Unable to unload driver module \"%s\": %s\n",
modname, strerror(errno));
return ret;
}
int do_dhcp_request(int *ipaddr, int *gateway, int *mask,
int *dns1, int *dns2, int *server, int *lease) {
/* For test driver, always report success */
if (strcmp(primary_iface, WIFI_TEST_INTERFACE) == 0)
return 0;
if (ifc_init() < 0)
return -1;
if (do_dhcp(primary_iface) < 0) {
ifc_close();
return -1;
}
ifc_close();
get_dhcp_info(ipaddr, gateway, mask, dns1, dns2, server, lease);
return 0;
}
const char *get_dhcp_error_string() {
return dhcp_lasterror();
}
#ifdef WIFI_DRIVER_STATE_CTRL_PARAM
int wifi_change_driver_state(const char *state)
{
int len;
int fd;
int ret = 0;
if (!state)
return -1;
fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_STATE_CTRL_PARAM, O_WRONLY));
if (fd < 0) {
ALOGE("Failed to open driver state control param (%s)", strerror(errno));
return -1;
}
len = strlen(state) + 1;
if (TEMP_FAILURE_RETRY(write(fd, state, len)) != len) {
ALOGE("Failed to write driver state control param (%s)", strerror(errno));
ret = -1;
}
close(fd);
return ret;
}
#endif
int is_wifi_driver_loaded() {
char driver_status[PROPERTY_VALUE_MAX];
#ifdef WIFI_DRIVER_MODULE_PATH
FILE *proc;
char line[sizeof(DRIVER_MODULE_TAG)+10];
#endif
if (!property_get(DRIVER_PROP_NAME, driver_status, NULL)
|| strcmp(driver_status, "ok") != 0) {
return 0; /* driver not loaded */
}
#ifdef WIFI_DRIVER_MODULE_PATH
/*
* If the property says the driver is loaded, check to
* make sure that the property setting isn't just left
* over from a previous manual shutdown or a runtime
* crash.
*/
if ((proc = fopen(MODULE_FILE, "r")) == NULL) {
ALOGW("Could not open %s: %s", MODULE_FILE, strerror(errno));
property_set(DRIVER_PROP_NAME, "unloaded");
return 0;
}
while ((fgets(line, sizeof(line), proc)) != NULL) {
if (strncmp(line, DRIVER_MODULE_TAG, strlen(DRIVER_MODULE_TAG)) == 0) {
fclose(proc);
return 1;
}
}
fclose(proc);
property_set(DRIVER_PROP_NAME, "unloaded");
return 0;
#else
return 1;
#endif
}
int wifi_load_driver()
{
#ifdef WIFI_DRIVER_MODULE_PATH
char driver_status[PROPERTY_VALUE_MAX];
int count = 100; /* wait at most 20 seconds for completion */
if (is_wifi_driver_loaded()) {
return 0;
}
if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0)
return -1;
if (strcmp(FIRMWARE_LOADER,"") == 0) {
/* usleep(WIFI_DRIVER_LOADER_DELAY); */
property_set(DRIVER_PROP_NAME, "ok");
}
else {
property_set("ctl.start", FIRMWARE_LOADER);
}
sched_yield();
while (count-- > 0) {
if (property_get(DRIVER_PROP_NAME, driver_status, NULL)) {
if (strcmp(driver_status, "ok") == 0)
return 0;
else if (strcmp(driver_status, "failed") == 0) {
wifi_unload_driver();
return -1;
}
}
usleep(200000);
}
property_set(DRIVER_PROP_NAME, "timeout");
wifi_unload_driver();
return -1;
#else
#ifdef WIFI_DRIVER_STATE_CTRL_PARAM
if (is_wifi_driver_loaded()) {
return 0;
}
if (wifi_change_driver_state(WIFI_DRIVER_STATE_ON) < 0)
return -1;
#endif
property_set(DRIVER_PROP_NAME, "ok");
return 0;
#endif
}
int wifi_unload_driver()
{
usleep(200000); /* allow to finish interface down */
#ifdef WIFI_DRIVER_MODULE_PATH
if (rmmod(DRIVER_MODULE_NAME) == 0) {
int count = 20; /* wait at most 10 seconds for completion */
while (count-- > 0) {
if (!is_wifi_driver_loaded())
break;
usleep(500000);
}
usleep(500000); /* allow card removal */
if (count) {
return 0;
}
return -1;
} else
return -1;
#else
#ifdef WIFI_DRIVER_STATE_CTRL_PARAM
if (is_wifi_driver_loaded()) {
if (wifi_change_driver_state(WIFI_DRIVER_STATE_OFF) < 0)
return -1;
}
#endif
property_set(DRIVER_PROP_NAME, "unloaded");
return 0;
#endif
}
int ensure_entropy_file_exists()
{
int ret;
int destfd;
ret = access(SUPP_ENTROPY_FILE, R_OK|W_OK);
if ((ret == 0) || (errno == EACCES)) {
if ((ret != 0) &&
(chmod(SUPP_ENTROPY_FILE, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) != 0)) {
ALOGE("Cannot set RW to \"%s\": %s", SUPP_ENTROPY_FILE, strerror(errno));
return -1;
}
return 0;
}
destfd = TEMP_FAILURE_RETRY(open(SUPP_ENTROPY_FILE, O_CREAT|O_RDWR, 0660));
if (destfd < 0) {
ALOGE("Cannot create \"%s\": %s", SUPP_ENTROPY_FILE, strerror(errno));
return -1;
}
if (TEMP_FAILURE_RETRY(write(destfd, dummy_key, sizeof(dummy_key))) != sizeof(dummy_key)) {
ALOGE("Error writing \"%s\": %s", SUPP_ENTROPY_FILE, strerror(errno));
close(destfd);
return -1;
}
close(destfd);
/* chmod is needed because open() didn't set permisions properly */
if (chmod(SUPP_ENTROPY_FILE, 0660) < 0) {
ALOGE("Error changing permissions of %s to 0660: %s",
SUPP_ENTROPY_FILE, strerror(errno));
unlink(SUPP_ENTROPY_FILE);
return -1;
}
if (chown(SUPP_ENTROPY_FILE, AID_SYSTEM, AID_WIFI) < 0) {
ALOGE("Error changing group ownership of %s to %d: %s",
SUPP_ENTROPY_FILE, AID_WIFI, strerror(errno));
unlink(SUPP_ENTROPY_FILE);
return -1;
}
return 0;
}
int ensure_config_file_exists(const char *config_file)
{
char buf[2048];
int srcfd, destfd;
struct stat sb;
int nread;
int ret;
ret = access(config_file, R_OK|W_OK);
if ((ret == 0) || (errno == EACCES)) {
if ((ret != 0) &&
(chmod(config_file, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) != 0)) {
ALOGE("Cannot set RW to \"%s\": %s", config_file, strerror(errno));
return -1;
}
return 0;
} else if (errno != ENOENT) {
ALOGE("Cannot access \"%s\": %s", config_file, strerror(errno));
return -1;
}
srcfd = TEMP_FAILURE_RETRY(open(SUPP_CONFIG_TEMPLATE, O_RDONLY));
if (srcfd < 0) {
ALOGE("Cannot open \"%s\": %s", SUPP_CONFIG_TEMPLATE, strerror(errno));
return -1;
}
destfd = TEMP_FAILURE_RETRY(open(config_file, O_CREAT|O_RDWR, 0660));
if (destfd < 0) {
close(srcfd);
ALOGE("Cannot create \"%s\": %s", config_file, strerror(errno));
return -1;
}
while ((nread = TEMP_FAILURE_RETRY(read(srcfd, buf, sizeof(buf)))) != 0) {
if (nread < 0) {
ALOGE("Error reading \"%s\": %s", SUPP_CONFIG_TEMPLATE, strerror(errno));
close(srcfd);
close(destfd);
unlink(config_file);
return -1;
}
TEMP_FAILURE_RETRY(write(destfd, buf, nread));
}
close(destfd);
close(srcfd);
/* chmod is needed because open() didn't set permisions properly */
if (chmod(config_file, 0660) < 0) {
ALOGE("Error changing permissions of %s to 0660: %s",
config_file, strerror(errno));
unlink(config_file);
return -1;
}
if (chown(config_file, AID_SYSTEM, AID_WIFI) < 0) {
ALOGE("Error changing group ownership of %s to %d: %s",
config_file, AID_WIFI, strerror(errno));
unlink(config_file);
return -1;
}
return 0;
}
int wifi_start_supplicant(int p2p_supported)
{
char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
int count = 200; /* wait at most 20 seconds for completion */
const prop_info *pi;
unsigned serial = 0, i;
if (p2p_supported) {
strcpy(supplicant_name, P2P_SUPPLICANT_NAME);
strcpy(supplicant_prop_name, P2P_PROP_NAME);
/* Ensure p2p config file is created */
if (ensure_config_file_exists(P2P_CONFIG_FILE) < 0) {
ALOGE("Failed to create a p2p config file");
return -1;
}
} else {
strcpy(supplicant_name, SUPPLICANT_NAME);
strcpy(supplicant_prop_name, SUPP_PROP_NAME);
}
/* Check whether already running */
if (property_get(supplicant_prop_name, supp_status, NULL)
&& strcmp(supp_status, "running") == 0) {
return 0;
}
/* Before starting the daemon, make sure its config file exists */
if (ensure_config_file_exists(SUPP_CONFIG_FILE) < 0) {
ALOGE("Wi-Fi will not be enabled");
return -1;
}
if (ensure_entropy_file_exists() < 0) {
ALOGE("Wi-Fi entropy file was not created");
}
/* Clear out any stale socket files that might be left over. */
wpa_ctrl_cleanup();
/* Reset sockets used for exiting from hung state */
exit_sockets[0] = exit_sockets[1] = -1;
/*
* Get a reference to the status property, so we can distinguish
* the case where it goes stopped => running => stopped (i.e.,
* it start up, but fails right away) from the case in which
* it starts in the stopped state and never manages to start
* running at all.
*/
pi = __system_property_find(supplicant_prop_name);
if (pi != NULL) {
serial = __system_property_serial(pi);
}
property_get("wifi.interface", primary_iface, WIFI_TEST_INTERFACE);
property_set("ctl.start", supplicant_name);
sched_yield();
while (count-- > 0) {
if (pi == NULL) {
pi = __system_property_find(supplicant_prop_name);
}
if (pi != NULL) {
/*
* property serial updated means that init process is scheduled
* after we sched_yield, further property status checking is based on this */
if (__system_property_serial(pi) != serial) {
__system_property_read(pi, NULL, supp_status);
if (strcmp(supp_status, "running") == 0) {
return 0;
} else if (strcmp(supp_status, "stopped") == 0) {
return -1;
}
}
}
usleep(100000);
}
return -1;
}
int wifi_stop_supplicant(int p2p_supported)
{
char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
int count = 50; /* wait at most 5 seconds for completion */
if (p2p_supported) {
strcpy(supplicant_name, P2P_SUPPLICANT_NAME);
strcpy(supplicant_prop_name, P2P_PROP_NAME);
} else {
strcpy(supplicant_name, SUPPLICANT_NAME);
strcpy(supplicant_prop_name, SUPP_PROP_NAME);
}
/* Check whether supplicant already stopped */
if (property_get(supplicant_prop_name, supp_status, NULL)
&& strcmp(supp_status, "stopped") == 0) {
return 0;
}
property_set("ctl.stop", supplicant_name);
sched_yield();
while (count-- > 0) {
if (property_get(supplicant_prop_name, supp_status, NULL)) {
if (strcmp(supp_status, "stopped") == 0)
return 0;
}
usleep(100000);
}
ALOGE("Failed to stop supplicant");
return -1;
}
int wifi_connect_on_socket_path(const char *path)
{
char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
/* Make sure supplicant is running */
if (!property_get(supplicant_prop_name, supp_status, NULL)
|| strcmp(supp_status, "running") != 0) {
ALOGE("Supplicant not running, cannot connect");
return -1;
}
ctrl_conn = wpa_ctrl_open(path);
if (ctrl_conn == NULL) {
ALOGE("Unable to open connection to supplicant on \"%s\": %s",
path, strerror(errno));
return -1;
}
monitor_conn = wpa_ctrl_open(path);
if (monitor_conn == NULL) {
wpa_ctrl_close(ctrl_conn);
ctrl_conn = NULL;
return -1;
}
if (wpa_ctrl_attach(monitor_conn) != 0) {
wpa_ctrl_close(monitor_conn);
wpa_ctrl_close(ctrl_conn);
ctrl_conn = monitor_conn = NULL;
return -1;
}
if (socketpair(AF_UNIX, SOCK_STREAM, 0, exit_sockets) == -1) {
wpa_ctrl_close(monitor_conn);
wpa_ctrl_close(ctrl_conn);
ctrl_conn = monitor_conn = NULL;
return -1;
}
return 0;
}
/* Establishes the control and monitor socket connections on the interface */
int wifi_connect_to_supplicant()
{
static char path[PATH_MAX];
if (access(IFACE_DIR, F_OK) == 0) {
snprintf(path, sizeof(path), "%s/%s", IFACE_DIR, primary_iface);
} else {
snprintf(path, sizeof(path), "@android:wpa_%s", primary_iface);
}
return wifi_connect_on_socket_path(path);
}
int wifi_send_command(const char *cmd, char *reply, size_t *reply_len)
{
int ret;
if (ctrl_conn == NULL) {
ALOGV("Not connected to wpa_supplicant - \"%s\" command dropped.\n", cmd);
return -1;
}
ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), reply, reply_len, NULL);
if (ret == -2) {
ALOGD("'%s' command timed out.\n", cmd);
/* unblocks the monitor receive socket for termination */
TEMP_FAILURE_RETRY(write(exit_sockets[0], "T", 1));
return -2;
} else if (ret < 0 || strncmp(reply, "FAIL", 4) == 0) {
return -1;
}
if (strncmp(cmd, "PING", 4) == 0) {
reply[*reply_len] = '\0';
}
return 0;
}
int wifi_supplicant_connection_active()
{
char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
if (property_get(supplicant_prop_name, supp_status, NULL)) {
if (strcmp(supp_status, "stopped") == 0)
return -1;
}
return 0;
}
int wifi_ctrl_recv(char *reply, size_t *reply_len)
{
int res;
int ctrlfd = wpa_ctrl_get_fd(monitor_conn);
struct pollfd rfds[2];
memset(rfds, 0, 2 * sizeof(struct pollfd));
rfds[0].fd = ctrlfd;
rfds[0].events |= POLLIN;
rfds[1].fd = exit_sockets[1];
rfds[1].events |= POLLIN;
do {
res = TEMP_FAILURE_RETRY(poll(rfds, 2, 30000));
if (res < 0) {
ALOGE("Error poll = %d", res);
return res;
} else if (res == 0) {
/* timed out, check if supplicant is active
* or not ..
*/
res = wifi_supplicant_connection_active();
if (res < 0)
return -2;
}
} while (res == 0);
if (rfds[0].revents & POLLIN) {
return wpa_ctrl_recv(monitor_conn, reply, reply_len);
}
/* it is not rfds[0], then it must be rfts[1] (i.e. the exit socket)
* or we timed out. In either case, this call has failed ..
*/
return -2;
}
int wifi_wait_on_socket(char *buf, size_t buflen)
{
size_t nread = buflen - 1;
int result;
char *match, *match2;
if (monitor_conn == NULL) {
return snprintf(buf, buflen, "IFNAME=%s %s - connection closed",
primary_iface, WPA_EVENT_TERMINATING);
}
result = wifi_ctrl_recv(buf, &nread);
/* Terminate reception on exit socket */
if (result == -2) {
return snprintf(buf, buflen, "IFNAME=%s %s - connection closed",
primary_iface, WPA_EVENT_TERMINATING);
}
if (result < 0) {
ALOGD("wifi_ctrl_recv failed: %s\n", strerror(errno));
return snprintf(buf, buflen, "IFNAME=%s %s - recv error",
primary_iface, WPA_EVENT_TERMINATING);
}
buf[nread] = '\0';
/* Check for EOF on the socket */
if (result == 0 && nread == 0) {
/* Fabricate an event to pass up */
ALOGD("Received EOF on supplicant socket\n");
return snprintf(buf, buflen, "IFNAME=%s %s - signal 0 received",
primary_iface, WPA_EVENT_TERMINATING);
}
/*
* Events strings are in the format
*
* IFNAME=iface <N>CTRL-EVENT-XXX
* or
* <N>CTRL-EVENT-XXX
*
* where N is the message level in numerical form (0=VERBOSE, 1=DEBUG,
* etc.) and XXX is the event name. The level information is not useful
* to us, so strip it off.
*/
if (strncmp(buf, IFNAME, IFNAMELEN) == 0) {
match = strchr(buf, ' ');
if (match != NULL) {
if (match[1] == '<') {
match2 = strchr(match + 2, '>');
if (match2 != NULL) {
nread -= (match2 - match);
memmove(match + 1, match2 + 1, nread - (match - buf) + 1);
}
}
} else {
return snprintf(buf, buflen, "%s", WPA_EVENT_IGNORE);
}
} else if (buf[0] == '<') {
match = strchr(buf, '>');
if (match != NULL) {
nread -= (match + 1 - buf);
memmove(buf, match + 1, nread + 1);
ALOGV("supplicant generated event without interface - %s\n", buf);
}
} else {
/* let the event go as is! */
ALOGW("supplicant generated event without interface and without message level - %s\n", buf);
}
return nread;
}
int wifi_wait_for_event(char *buf, size_t buflen)
{
return wifi_wait_on_socket(buf, buflen);
}
void wifi_close_sockets()
{
if (ctrl_conn != NULL) {
wpa_ctrl_close(ctrl_conn);
ctrl_conn = NULL;
}
if (monitor_conn != NULL) {
wpa_ctrl_close(monitor_conn);
monitor_conn = NULL;
}
if (exit_sockets[0] >= 0) {
close(exit_sockets[0]);
exit_sockets[0] = -1;
}
if (exit_sockets[1] >= 0) {
close(exit_sockets[1]);
exit_sockets[1] = -1;
}
}
void wifi_close_supplicant_connection()
{
char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
int count = 50; /* wait at most 5 seconds to ensure init has stopped stupplicant */
wifi_close_sockets();
while (count-- > 0) {
if (property_get(supplicant_prop_name, supp_status, NULL)) {
if (strcmp(supp_status, "stopped") == 0)
return;
}
usleep(100000);
}
}
int wifi_command(const char *command, char *reply, size_t *reply_len)
{
return wifi_send_command(command, reply, reply_len);
}
const char *wifi_get_fw_path(int fw_type)
{
switch (fw_type) {
case WIFI_GET_FW_PATH_STA:
return WIFI_DRIVER_FW_PATH_STA;
case WIFI_GET_FW_PATH_AP:
return WIFI_DRIVER_FW_PATH_AP;
case WIFI_GET_FW_PATH_P2P:
return WIFI_DRIVER_FW_PATH_P2P;
}
return NULL;
}
int wifi_change_fw_path(const char *fwpath)
{
int len;
int fd;
int ret = 0;
if (!fwpath)
return ret;
fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_FW_PATH_PARAM, O_WRONLY));
if (fd < 0) {
ALOGE("Failed to open wlan fw path param (%s)", strerror(errno));
return -1;
}
len = strlen(fwpath) + 1;
if (TEMP_FAILURE_RETRY(write(fd, fwpath, len)) != len) {
ALOGE("Failed to write wlan fw path param (%s)", strerror(errno));
ret = -1;
}
close(fd);
return ret;
}