public:
LinkLayerStatsCommand(wifi_interface_handle handle, wifi_link_layer_params params)
: WifiCommand(handle, 0), mParams(params)
- { }
+ {
+ mStatsClearReqMask = 0;
+ mStatsClearRspMask = 0;
+ mStopReq = 0 ;
+ mStopRsp = NULL;
+
+ }
LinkLayerStatsCommand(wifi_interface_handle handle,
u32 stats_clear_req_mask, u32 *stats_clear_rsp_mask, u8 stop_req, u8 *stop_rsp)
: WifiCommand(handle, 0), mStatsClearReqMask(stats_clear_req_mask), mStatsClearRspMask(stats_clear_rsp_mask),
mStopReq(stop_req), mStopRsp(stop_rsp)
- { }
+ {
+ memset(&mParams,0,sizeof(wifi_link_layer_params));
+ }
int createSetRequest(WifiRequest& request) {
int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_LLS_SET_INFO);
return result;
}
- ALOGD("Successfully set Link Layer Statistics measurement");
return result;
}
return result;
}
- ALOGD("Successfully clear Link Layer Statistics measurement");
return result;
}
}
virtual int create() {
- ALOGI("Creating message to get link statistics");
-
int ret = mMsg.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_LLS_GET_INFO);
if (ret < 0) {
ALOGE("Failed to create %x - %d", SLSI_NL80211_VENDOR_SUBCMD_LLS_GET_INFO, ret);
protected:
virtual int handleResponse(WifiEvent& reply) {
-
- ALOGI("In GetLinkStatsCommand::handleResponse");
-
if (reply.get_cmd() != NL80211_CMD_VENDOR) {
ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
return NL_SKIP;
}
-
int id = reply.get_vendor_id();
int subcmd = reply.get_vendor_subcmd();
-
- ALOGI("Id = %0x, subcmd = %d", id, subcmd);
-
u8 *data = (u8 *)reply.get_vendor_data();
int len = reply.get_vendor_data_len();
-
+ int num_radios = 0, i = 0;
+ num_radios = data[0];
+ data += sizeof(data[0]);
// assuming max peers is 16
wifi_iface_stat *iface_stat = (wifi_iface_stat *) malloc(sizeof(wifi_iface_stat) + sizeof(wifi_peer_info) * 16);
- // max channel is 38 (14 2.4GHz and 24 5GHz)
- wifi_radio_stat *radio_stat = (wifi_radio_stat *) malloc(sizeof(wifi_radio_stat) + sizeof(wifi_channel_stat) * 38);
+ if (!iface_stat) {
+ ALOGE("Memory alloc failed for iface_stat in response handler!!!");
+ return NL_SKIP;
+ }
- if (!iface_stat || !radio_stat) {
- ALOGE("Memory alloc failed in response handler!!!");
+ // max channel is 39 (14 2.4GHz and 25 5GHz)
+ wifi_radio_stat *radio_stat = (wifi_radio_stat *) malloc((num_radios * sizeof(wifi_radio_stat)) + sizeof(wifi_channel_stat) * 39);
+ wifi_radio_stat *radio_stat2;
+ radio_stat2 = radio_stat;
+ if (!radio_stat) {
+ ALOGE("Memory alloc failed for radio_stat in response handler!!!");
+ free(iface_stat);
return NL_SKIP;
}
+ /* Data sent from driver does not contain num_tx_levels and tx_time per level. So copy
+ * radio data in two parts - 1st part until num_tx_levels and 2nd part from rx_time.
+ * channel data is copied separately
+ */
+ int radio_data_len1,radio_data_len2;
+ radio_data_len1 = (u8 *)&(radio_stat->num_tx_levels) - (u8*)radio_stat;
+ radio_data_len2 = (u8 *)(radio_stat->channels) - (u8*)&(radio_stat->rx_time);
+
//kernel is 64 bit. if userspace is 64 bit, typecastting buffer works else, make corrections
if (sizeof(iface_stat->iface) == 8) {
memcpy(iface_stat, data, sizeof(wifi_iface_stat) + sizeof(wifi_peer_info) * ((wifi_iface_stat *)data)->num_peers);
data += sizeof(wifi_iface_stat) + sizeof(wifi_peer_info) * ((wifi_iface_stat *)data)->num_peers;
- memcpy(radio_stat, data, sizeof(wifi_radio_stat) + sizeof(wifi_channel_stat)* ((wifi_radio_stat *)data)->num_channels);
} else {
- /* for 64 bit kernel ad 32 bit user space, there is 4 byte extra at the beging and another 4 byte pad after 80 bytes
+ /* for 64 bit kernel ad 32 bit user space, there is 4 byte extra at the begining and another 4 byte pad after 80 bytes
* so remove first 4 and 81-84 bytes from NL buffer.*/
data += 4;
memcpy(iface_stat, data, 80);
data += sizeof(wifi_iface_stat) - 80;
memcpy(iface_stat->peer_info, data, sizeof(wifi_peer_info) * iface_stat->num_peers);
data += sizeof(wifi_peer_info) * iface_stat->num_peers;
- memcpy(radio_stat, data, sizeof(wifi_radio_stat));
- data += sizeof(wifi_radio_stat);
- memcpy(radio_stat->channels, data, sizeof(wifi_channel_stat) * radio_stat->num_channels);
}
+ for (i = 0; i < num_radios; i++) {
+ memcpy(radio_stat2, data, sizeof(*radio_stat2));
+ data += sizeof(*radio_stat2);
+ memcpy(radio_stat2->channels, data, sizeof(wifi_channel_stat)* radio_stat2->num_channels);
+ data += sizeof(wifi_channel_stat)* radio_stat2->num_channels;
+ radio_stat2=(wifi_radio_stat *) ((u8 *)radio_stat2+ sizeof(wifi_radio_stat) +
+ (sizeof(wifi_channel_stat) * radio_stat2->num_channels ));
+ }
iface_stat->iface = iface;
- (*mHandler.on_link_stats_results)(id, iface_stat, 1, radio_stat);
+ (*mHandler.on_link_stats_results)(id, iface_stat, num_radios, radio_stat);
free(iface_stat);
free(radio_stat);
return NL_OK;