1
2 #include <stdint.h>
3 #include <fcntl.h>
4 #include <sys/socket.h>
5 #include <netlink/genl/genl.h>
6 #include <netlink/genl/family.h>
7 #include <netlink/genl/ctrl.h>
8 #include <linux/rtnetlink.h>
9 #include <netpacket/packet.h>
10 #include <linux/filter.h>
11 #include <linux/errqueue.h>
12
13 #include <linux/pkt_sched.h>
14 #include <netlink/object-api.h>
15 #include <netlink/netlink.h>
16 #include <netlink/socket.h>
17 #include <netlink/handlers.h>
18
19 #include "sync.h"
20
21 #define LOG_TAG "WifiHAL"
22
23 #include <utils/Log.h>
24
25 #include "wifi_hal.h"
26 #include "common.h"
27 #include "cpp_bindings.h"
28
29
30 enum {
31 LSTATS_SUBCMD_GET_INFO = ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START,
32 };
33
34 class GetLinkStatsCommand : public WifiCommand
35 {
36 wifi_stats_result_handler mHandler;
37 public:
GetLinkStatsCommand(wifi_interface_handle iface,wifi_stats_result_handler handler)38 GetLinkStatsCommand(wifi_interface_handle iface, wifi_stats_result_handler handler)
39 : WifiCommand("GetLinkStatsCommand", iface, 0), mHandler(handler)
40 { }
41
create()42 virtual int create() {
43 // ALOGI("Creating message to get link statistics; iface = %d", mIfaceInfo->id);
44
45 int ret = mMsg.create(GOOGLE_OUI, LSTATS_SUBCMD_GET_INFO);
46 if (ret < 0) {
47 ALOGE("Failed to create %x - %d", LSTATS_SUBCMD_GET_INFO, ret);
48 return ret;
49 }
50
51 return ret;
52 }
53
54 protected:
handleResponse(WifiEvent & reply)55 virtual int handleResponse(WifiEvent& reply) {
56
57 // ALOGI("In GetLinkStatsCommand::handleResponse");
58
59 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
60 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
61 return NL_SKIP;
62 }
63
64 int id = reply.get_vendor_id();
65 int subcmd = reply.get_vendor_subcmd();
66
67 // ALOGI("Id = %0x, subcmd = %d", id, subcmd);
68
69 void *data = reply.get_vendor_data();
70 int len = reply.get_vendor_data_len();
71 unsigned int num_chan = ((wifi_radio_stat *)data)->num_channels;
72 if (num_chan > 11) {
73 ALOGE("Incorrect number of channels = %d", num_chan);
74 // dump data before num_channels
75 ALOGE("radio: = %d", ((wifi_radio_stat *)data)->radio);
76 ALOGE("on_time: = %d", ((wifi_radio_stat *)data)->on_time);
77 ALOGE("tx_time: = %d", ((wifi_radio_stat *)data)->tx_time);
78 ALOGE("rx_time: = %d", ((wifi_radio_stat *)data)->rx_time);
79 ALOGE("on_time_scan: = %d", ((wifi_radio_stat *)data)->on_time_scan);
80 ALOGE("on_time_nbd: = %d", ((wifi_radio_stat *)data)->on_time_nbd);
81 ALOGE("on_time_gscan: = %d", ((wifi_radio_stat *)data)->on_time_gscan);
82 ALOGE("on_time_pno_scan: = %d", ((wifi_radio_stat *)data)->on_time_pno_scan);
83 ALOGE("on_time_hs20: = %d", ((wifi_radio_stat *)data)->on_time_hs20);
84 return NL_SKIP;
85 }
86 (*mHandler.on_link_stats_results)(id,
87 (wifi_iface_stat *)((char *)&((wifi_radio_stat *)data)->channels
88 + num_chan*sizeof(wifi_channel_stat)),
89 1, (wifi_radio_stat *)data);
90
91 return NL_OK;
92 }
93 };
94
wifi_get_link_stats(wifi_request_id id,wifi_interface_handle iface,wifi_stats_result_handler handler)95 wifi_error wifi_get_link_stats(wifi_request_id id,
96 wifi_interface_handle iface, wifi_stats_result_handler handler)
97 {
98 GetLinkStatsCommand command(iface, handler);
99 return (wifi_error) command.requestResponse();
100 }
101
102