Skip to content
Snippets Groups Projects
Commit ca16b3ff authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 4745538 from ce366b22 to pi-release

Change-Id: Ic87a77bdf5fee560bc2c9cc935a8f370c7657365
parents 2f685533 ce366b22
No related branches found
No related tags found
No related merge requests found
...@@ -144,6 +144,7 @@ typedef struct hal_info_s { ...@@ -144,6 +144,7 @@ typedef struct hal_info_s {
struct rssi_monitor_event_handler_s *rssi_handlers; struct rssi_monitor_event_handler_s *rssi_handlers;
wifi_capa capa; wifi_capa capa;
struct cld80211_ctx *cldctx; struct cld80211_ctx *cldctx;
bool apf_enabled;
} hal_info; } hal_info;
wifi_error wifi_register_handler(wifi_handle handle, int cmd, nl_recvmsg_msg_cb_t func, void *arg); wifi_error wifi_register_handler(wifi_handle handle, int cmd, nl_recvmsg_msg_cb_t func, void *arg);
......
...@@ -203,6 +203,8 @@ WifihalGeneric::WifihalGeneric(wifi_handle handle, int id, u32 vendor_id, ...@@ -203,6 +203,8 @@ WifihalGeneric::WifihalGeneric(wifi_handle handle, int id, u32 vendor_id,
filterLength = 0; filterLength = 0;
firmware_bus_max_size = 0; firmware_bus_max_size = 0;
mCapa = &(info->capa); mCapa = &(info->capa);
mfilter_packet_read_buffer = NULL;
mfilter_packet_length = 0;
} }
WifihalGeneric::~WifihalGeneric() WifihalGeneric::~WifihalGeneric()
...@@ -287,12 +289,25 @@ int WifihalGeneric::handleResponse(WifiEvent &reply) ...@@ -287,12 +289,25 @@ int WifihalGeneric::handleResponse(WifiEvent &reply)
break; break;
case QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER: case QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER:
{ {
int subCmd;
struct nlattr *tb_vendor[ struct nlattr *tb_vendor[
QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX + 1]; QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX + 1];
nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX, nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX,
(struct nlattr *)mVendorData, (struct nlattr *)mVendorData,
mDataLen, NULL); mDataLen, NULL);
if (tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD])
{
subCmd = nla_get_u32(
tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD]);
} else {
/*
* The older drivers may not send PACKET_FILTER_SUB_CMD as
* they support QCA_WLAN_GET_PACKET_FILTER_SIZE only.
*/
subCmd = QCA_WLAN_GET_PACKET_FILTER_SIZE;
}
if (subCmd == QCA_WLAN_GET_PACKET_FILTER_SIZE) {
if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION]) if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION])
{ {
ALOGE("%s: QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION" ALOGE("%s: QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION"
...@@ -312,6 +327,31 @@ int WifihalGeneric::handleResponse(WifiEvent &reply) ...@@ -312,6 +327,31 @@ int WifihalGeneric::handleResponse(WifiEvent &reply)
filterLength = nla_get_u32( filterLength = nla_get_u32(
tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH]); tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH]);
ALOGV("Max filter length Supported : %u", filterLength); ALOGV("Max filter length Supported : %u", filterLength);
} else if (subCmd == QCA_WLAN_READ_PACKET_FILTER) {
if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM])
{
ALOGE("%s: QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM"
" not found", __FUNCTION__);
return -EINVAL;
}
if (nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM])
< mfilter_packet_length)
{
ALOGE("%s: Expected packet filter length :%d but received only: %d bytes",
__FUNCTION__, mfilter_packet_length,
nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM]));
return -EINVAL;
}
memcpy(mfilter_packet_read_buffer,
nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM]),
mfilter_packet_length);
ALOGV("Filter Program length : %u", mfilter_packet_length);
} else {
ALOGE("%s: Unknown APF sub command received",
__FUNCTION__);
return -EINVAL;
}
} }
break; break;
...@@ -522,6 +562,10 @@ int WifihalGeneric::getFilterVersion() { ...@@ -522,6 +562,10 @@ int WifihalGeneric::getFilterVersion() {
int WifihalGeneric::getFilterLength() { int WifihalGeneric::getFilterLength() {
return filterLength; return filterLength;
} }
void WifihalGeneric::setPacketBufferParams(u8 *host_packet_buffer, int packet_length) {
mfilter_packet_read_buffer = host_packet_buffer;
mfilter_packet_length = packet_length;
}
int WifihalGeneric::getBusSize() { int WifihalGeneric::getBusSize() {
return firmware_bus_max_size; return firmware_bus_max_size;
......
...@@ -90,7 +90,9 @@ private: ...@@ -90,7 +90,9 @@ private:
int filterLength; int filterLength;
int firmware_bus_max_size; int firmware_bus_max_size;
wifi_capa *mCapa; wifi_capa *mCapa;
/* Packet Filter buffer and length */
u8 *mfilter_packet_read_buffer;
int mfilter_packet_length;
virtual wifi_error wifiParseCapabilities(struct nlattr **tbVendor); virtual wifi_error wifiParseCapabilities(struct nlattr **tbVendor);
public: public:
...@@ -101,6 +103,7 @@ public: ...@@ -101,6 +103,7 @@ public:
virtual void getResponseparams(feature_set *pset); virtual void getResponseparams(feature_set *pset);
virtual void setMaxSetSize(int set_size_max); virtual void setMaxSetSize(int set_size_max);
virtual void setSizePtr(int *set_size); virtual void setSizePtr(int *set_size);
virtual void setPacketBufferParams(u8 *host_packet_buffer, int packet_length);
virtual void setConcurrencySet(feature_set set[]); virtual void setConcurrencySet(feature_set set[]);
virtual int getFilterVersion(); virtual int getFilterVersion();
virtual int getFilterLength(); virtual int getFilterLength();
......
...@@ -428,6 +428,14 @@ enum packet_filter_sub_cmd ...@@ -428,6 +428,14 @@ enum packet_filter_sub_cmd
{ {
QCA_WLAN_SET_PACKET_FILTER = 1, QCA_WLAN_SET_PACKET_FILTER = 1,
QCA_WLAN_GET_PACKET_FILTER_SIZE = 2, QCA_WLAN_GET_PACKET_FILTER_SIZE = 2,
/* For writing packet filter program + data */
QCA_WLAN_WRITE_PACKET_FILTER = 3,
/* For reading packet filter data */
QCA_WLAN_READ_PACKET_FILTER = 4,
/* Enable APF faeature */
QCA_WLAN_ENABLE_PACKET_FILTER = 5,
/* Disable APF faeature */
QCA_WLAN_DISABLE_PACKET_FILTER = 6,
}; };
enum qca_wlan_vendor_attr_packet_filter enum qca_wlan_vendor_attr_packet_filter
...@@ -440,6 +448,10 @@ enum qca_wlan_vendor_attr_packet_filter ...@@ -440,6 +448,10 @@ enum qca_wlan_vendor_attr_packet_filter
QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH, QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH,
QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET, QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM, QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM,
/* The length of the program in the write buffer,
* the write buffer may have program+data
*/
QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROG_LENGTH,
/* keep last */ /* keep last */
QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_AFTER_LAST,
......
...@@ -85,6 +85,8 @@ static wifi_error wifi_set_packet_filter(wifi_interface_handle iface, ...@@ -85,6 +85,8 @@ static wifi_error wifi_set_packet_filter(wifi_interface_handle iface,
const u8 *program, u32 len); const u8 *program, u32 len);
static wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle handle, static wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle handle,
u32 *version, u32 *max_len); u32 *version, u32 *max_len);
static wifi_error wifi_read_packet_filter(wifi_interface_handle handle,
u32 src_offset, u8 *host_dst, u32 length);
static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface, static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface,
u8 enable); u8 enable);
wifi_error wifi_get_wake_reason_stats(wifi_interface_handle iface, wifi_error wifi_get_wake_reason_stats(wifi_interface_handle iface,
...@@ -404,6 +406,7 @@ wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) { ...@@ -404,6 +406,7 @@ wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) {
fn->wifi_nan_get_version = nan_get_version; fn->wifi_nan_get_version = nan_get_version;
fn->wifi_set_packet_filter = wifi_set_packet_filter; fn->wifi_set_packet_filter = wifi_set_packet_filter;
fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities; fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities;
fn->wifi_read_packet_filter = wifi_read_packet_filter;
fn->wifi_nan_get_capabilities = nan_get_capabilities; fn->wifi_nan_get_capabilities = nan_get_capabilities;
fn->wifi_nan_data_interface_create = nan_data_interface_create; fn->wifi_nan_data_interface_create = nan_data_interface_create;
fn->wifi_nan_data_interface_delete = nan_data_interface_delete; fn->wifi_nan_data_interface_delete = nan_data_interface_delete;
...@@ -1492,6 +1495,8 @@ static wifi_error wifi_set_packet_filter(wifi_interface_handle iface, ...@@ -1492,6 +1495,8 @@ static wifi_error wifi_set_packet_filter(wifi_interface_handle iface,
current_offset += min(info->firmware_bus_max_size, len); current_offset += min(info->firmware_bus_max_size, len);
} while (current_offset < len); } while (current_offset < len);
info->apf_enabled = !!len;
cleanup: cleanup:
if (vCommand) if (vCommand)
delete vCommand; delete vCommand;
...@@ -1599,3 +1604,283 @@ cleanup: ...@@ -1599,3 +1604,283 @@ cleanup:
delete vCommand; delete vCommand;
return ret; return ret;
} }
/**
* Copy 'len' bytes of raw data from host memory at source address 'program'
* to APF (Android Packet Filter) working memory starting at offset 'dst_offset'.
* The size of the program lenght passed to the interpreter is set to
* 'progaram_lenght'
*
* The implementation is allowed to tranlate this wrtie into a series of smaller
* writes,but this function is not allowed to return untill all write operations
* have been completed
* additionally visible memory not targeted by this function must remain
* unchanged
* @param dst_offset write offset in bytes relative to the beginning of the APF
* working memory with logical address 0X000. Must be a multiple of 4
*
* @param program host memory to copy bytes from. Must be 4B aligned
*
* @param len the number of bytes to copy from the bost into the APF working
* memory
*
* @param program_length new length of the program instructions in bytes to pass
* to the interpreter
*/
wifi_error wifi_write_packet_filter(wifi_interface_handle iface,
u32 dst_offset, const u8 *program,
u32 len, u32 program_length)
{
wifi_error ret;
struct nlattr *nlData;
WifiVendorCommand *vCommand = NULL;
u32 current_offset = 0;
wifi_handle wifiHandle = getWifiHandle(iface);
hal_info *info = getHalInfo(wifiHandle);
/* len=0 clears the filters in driver/firmware */
if (len != 0 && program == NULL) {
ALOGE("%s: No valid program provided. Exit.",
__func__);
return WIFI_ERROR_INVALID_ARGS;
}
do {
ret = initialize_vendor_cmd(iface, get_requestid(),
QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
&vCommand);
if (ret != WIFI_SUCCESS) {
ALOGE("%s: Initialization failed", __FUNCTION__);
return ret;
}
/* Add the vendor specific attributes for the NL command. */
nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
if (!nlData)
goto cleanup;
ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
QCA_WLAN_WRITE_PACKET_FILTER);
if (ret != WIFI_SUCCESS)
goto cleanup;
ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID,
PACKET_FILTER_ID);
if (ret != WIFI_SUCCESS)
goto cleanup;
ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH,
len);
if (ret != WIFI_SUCCESS)
goto cleanup;
ret = vCommand->put_u32(
QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
dst_offset + current_offset);
if (ret != WIFI_SUCCESS)
goto cleanup;
ret = vCommand->put_u32(
QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROG_LENGTH,
program_length);
if (ret != WIFI_SUCCESS)
goto cleanup;
ret = vCommand->put_bytes(
QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM,
(char *)&program[current_offset],
min(info->firmware_bus_max_size,
len - current_offset));
if (ret!= WIFI_SUCCESS) {
ALOGE("%s: failed to put program", __FUNCTION__);
goto cleanup;
}
vCommand->attr_end(nlData);
ret = vCommand->requestResponse();
if (ret != WIFI_SUCCESS) {
ALOGE("%s: requestResponse Error:%d",__func__, ret);
goto cleanup;
}
/* destroy the object after sending each fragment to driver */
delete vCommand;
vCommand = NULL;
current_offset += min(info->firmware_bus_max_size,
len - current_offset);
} while (current_offset < len);
cleanup:
if (vCommand)
delete vCommand;
return ret;
}
wifi_error wifi_enable_packet_filter(wifi_interface_handle handle,
u32 enable)
{
wifi_error ret;
struct nlattr *nlData;
WifiVendorCommand *vCommand = NULL;
u32 subcmd;
wifi_handle wifiHandle = getWifiHandle(handle);
hal_info *info = getHalInfo(wifiHandle);
ret = initialize_vendor_cmd(handle, get_requestid(),
QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
&vCommand);
if (ret != WIFI_SUCCESS) {
ALOGE("%s: Initialization failed", __func__);
return ret;
}
/* Add the vendor specific attributes for the NL command. */
nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
if (!nlData)
goto cleanup;
subcmd = enable ? QCA_WLAN_ENABLE_PACKET_FILTER :
QCA_WLAN_DISABLE_PACKET_FILTER;
ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
subcmd);
if (ret != WIFI_SUCCESS)
goto cleanup;
vCommand->attr_end(nlData);
ret = vCommand->requestResponse();
if (ret != WIFI_SUCCESS) {
ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret);
goto cleanup;
}
info->apf_enabled = !!enable;
cleanup:
if (vCommand)
delete vCommand;
return ret;
}
/**
* Copy 'length' bytes of raw data from APF (Android Packet Filter) working
* memory to host memory starting at offset src_offset into host memory
* pointed to by host_dst.
* Memory can be text, data or some combination of the two. The implementiion is
* allowed to translate this read into a series of smaller reads, but this
* function is not allowed to return untill all the reads operations
* into host_dst have been completed.
*
* @param src_offset offset in bytes of destination memory within APF working
* memory
*
* @param host_dst host memory to copy into. Must be 4B aligned.
*
* @param length the number of bytes to copy from the APF working memory to the
* host.
*/
static wifi_error wifi_read_packet_filter(wifi_interface_handle handle,
u32 src_offset, u8 *host_dst, u32 length)
{
wifi_error ret;
struct nlattr *nlData;
WifihalGeneric *vCommand = NULL;
interface_info *ifaceInfo = getIfaceInfo(handle);
wifi_handle wifiHandle = getWifiHandle(handle);
hal_info *info = getHalInfo(wifiHandle);
/*Temporary varibles to support the read complete length in chunks */
u8 *temp_host_dst;
u32 remainingLengthToBeRead, currentLength;
u8 apf_locally_disabled = 0;
/*Initializing the temporary variables*/
temp_host_dst = host_dst;
remainingLengthToBeRead = length;
if (info->apf_enabled) {
/* Disable APF only when not disabled by framework before calling
* wifi_read_packet_filter()
*/
ret = wifi_enable_packet_filter(handle, 0);
if (ret != WIFI_SUCCESS) {
ALOGE("%s: Failed to disable APF", __FUNCTION__);
return ret;
}
apf_locally_disabled = 1;
}
/**
* Read the complete length in chunks of size less or equal to firmware bus
* max size
*/
while (remainingLengthToBeRead)
{
vCommand = new WifihalGeneric(wifiHandle, 0, OUI_QCA,
QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER);
if (vCommand == NULL) {
ALOGE("%s: Error vCommand NULL", __FUNCTION__);
ret = WIFI_ERROR_OUT_OF_MEMORY;
break;
}
/* Create the message */
ret = vCommand->create();
if (ret != WIFI_SUCCESS)
break;
ret = vCommand->set_iface_id(ifaceInfo->name);
if (ret != WIFI_SUCCESS)
break;
/* Add the vendor specific attributes for the NL command. */
nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
if (!nlData)
break;
ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
QCA_WLAN_READ_PACKET_FILTER);
if (ret != WIFI_SUCCESS)
break;
currentLength = min(remainingLengthToBeRead, info->firmware_bus_max_size);
ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH,
currentLength);
if (ret != WIFI_SUCCESS)
break;
ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
src_offset);
if (ret != WIFI_SUCCESS)
break;
vCommand->setPacketBufferParams(temp_host_dst, currentLength);
vCommand->attr_end(nlData);
ret = vCommand->requestResponse();
if (ret != WIFI_SUCCESS) {
ALOGE("%s: requestResponse() error: %d current_len = %u, src_offset = %u",
__FUNCTION__, ret, currentLength, src_offset);
break;
}
remainingLengthToBeRead -= currentLength;
temp_host_dst += currentLength;
src_offset += currentLength;
delete vCommand;
vCommand = NULL;
}
/* Re enable APF only when disabled above within this API */
if (apf_locally_disabled) {
wifi_error status;
status = wifi_enable_packet_filter(handle, 1);
if (status != WIFI_SUCCESS)
ALOGE("%s: Failed to enable APF", __FUNCTION__);
/* Prefer to return read status if read fails */
if (ret == WIFI_SUCCESS)
ret = status;
}
delete vCommand;
return ret;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment