1aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee#include <stdint.h>
2aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee#include <fcntl.h>
3aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee#include <sys/socket.h>
4aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee#include <netlink/genl/genl.h>
5aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee#include <netlink/genl/family.h>
6aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee#include <netlink/genl/ctrl.h>
7aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee#include <linux/rtnetlink.h>
8aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee#include <netpacket/packet.h>
9aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee#include <linux/filter.h>
10aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee#include <linux/errqueue.h>
11aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
12aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee#include <linux/pkt_sched.h>
13aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee#include <netlink/object-api.h>
14aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee#include <netlink/netlink.h>
15aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee#include <netlink/socket.h>
16aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee#include <netlink-types.h>
17aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
18aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee#include "nl80211_copy.h"
19aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee#include "sync.h"
20aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
21aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee#define LOG_TAG  "WifiHAL"
22aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
23aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee#include <utils/Log.h>
24aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
25aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee#include "wifi_hal.h"
26aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee#include "common.h"
27aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee#include "cpp_bindings.h"
28aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
29aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Leeusing namespace android;
30aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
31aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Leetypedef enum {
32aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    LOGGER_START_LOGGING = ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START,
33aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    LOGGER_TRIGGER_MEM_DUMP,
34aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    LOGGER_GET_MEM_DUMP,
35aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    LOGGER_GET_VER,
36aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    LOGGER_GET_RING_STATUS,
37aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    LOGGER_GET_RING_DATA,
38aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    LOGGER_GET_FEATURE,
39c604b53461cfea0a1e6f6f5ad84b0a35be69b8e0JerryLee    LOGGER_RESET_LOGGING,
407e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    LOGGER_TRIGGER_DRIVER_MEM_DUMP,
417e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    LOGGER_GET_DRIVER_MEM_DUMP,
427e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    LOGGER_START_PKT_FATE_MONITORING,
437e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    LOGGER_GET_TX_PKT_FATES,
447e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    LOGGER_GET_RX_PKT_FATES,
45aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee} DEBUG_SUB_COMMAND;
46aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
47aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Leetypedef enum {
48aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    LOGGER_ATTRIBUTE_DRIVER_VER,
49aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    LOGGER_ATTRIBUTE_FW_VER,
50aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    LOGGER_ATTRIBUTE_RING_ID,
51aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    LOGGER_ATTRIBUTE_RING_NAME,
52aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    LOGGER_ATTRIBUTE_RING_FLAGS,
53aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    LOGGER_ATTRIBUTE_LOG_LEVEL,
54aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    LOGGER_ATTRIBUTE_LOG_TIME_INTVAL,
55aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE,
56aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    LOGGER_ATTRIBUTE_FW_DUMP_LEN,
57aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    LOGGER_ATTRIBUTE_FW_DUMP_DATA,
58aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    // LOGGER_ATTRIBUTE_FW_ERR_CODE,
59aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    LOGGER_ATTRIBUTE_RING_DATA,
60aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    LOGGER_ATTRIBUTE_RING_STATUS,
61aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    LOGGER_ATTRIBUTE_RING_NUM,
627e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN,
637e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA,
647e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    LOGGER_ATTRIBUTE_PKT_FATE_NUM,
657e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    LOGGER_ATTRIBUTE_PKT_FATE_DATA,
66aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee} LOGGER_ATTRIBUTE;
67aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
68aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Leetypedef enum {
69aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    DEBUG_OFF = 0,
70aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    DEBUG_NORMAL,
71aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    DEBUG_VERBOSE,
72aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    DEBUG_VERY,
73aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    DEBUG_VERY_VERY,
74aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee} LOGGER_LEVEL;
75aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
76aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Leetypedef enum {
77aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    GET_FW_VER,
78aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    GET_DRV_VER,
79aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    GET_RING_DATA,
80aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    GET_RING_STATUS,
81aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    GET_FEATURE,
82aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    START_RING_LOG,
83aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee} GetCmdType;
84aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
857e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharmatypedef enum {
867e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    PACKET_MONITOR_START,
877e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    TX_PACKET_FATE,
887e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    RX_PACKET_FATE,
897e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma} PktFateReqType;
907e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma
91aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
92aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee///////////////////////////////////////////////////////////////////////////////
93aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Leeclass DebugCommand : public WifiCommand
94aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee{
95040ee11fb7c5f1781537ae4343c056c0a49dcfc5xinhe    char *mBuff;
96aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    int *mBuffSize;
97aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    u32 *mNumRings;
98040ee11fb7c5f1781537ae4343c056c0a49dcfc5xinhe    wifi_ring_buffer_status *mStatus;
99aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    unsigned int *mSupport;
100aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    u32 mVerboseLevel;
101aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    u32 mFlags;
102aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    u32 mMaxIntervalSec;
103aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    u32 mMinDataSize;
104aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    char *mRingName;
105aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    GetCmdType mType;
106aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
107aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Leepublic:
108aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
109aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    // constructor for get version
110040ee11fb7c5f1781537ae4343c056c0a49dcfc5xinhe    DebugCommand(wifi_interface_handle iface, char *buffer, int *buffer_size,
111aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            GetCmdType cmdType)
112d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        : WifiCommand("DebugCommand", iface, 0), mBuff(buffer), mBuffSize(buffer_size), mType
113d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        (cmdType)
114aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    {
115040ee11fb7c5f1781537ae4343c056c0a49dcfc5xinhe        memset(mBuff, 0, *mBuffSize);
116aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    }
117aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
118aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    // constructor for ring data
119aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    DebugCommand(wifi_interface_handle iface, char *ring_name, GetCmdType cmdType)
120d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        : WifiCommand("DebugCommand", iface, 0), mRingName(ring_name), mType(cmdType)
121aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    { }
122aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
123aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    // constructor for ring status
124aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    DebugCommand(wifi_interface_handle iface, u32 *num_rings,
125040ee11fb7c5f1781537ae4343c056c0a49dcfc5xinhe            wifi_ring_buffer_status *status, GetCmdType cmdType)
126d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        : WifiCommand("DebugCommand", iface, 0), mNumRings(num_rings), mStatus(status), mType(cmdType)
127aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    {
128040ee11fb7c5f1781537ae4343c056c0a49dcfc5xinhe        memset(mStatus, 0, sizeof(wifi_ring_buffer_status) * (*mNumRings));
129aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    }
130aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
131aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    // constructor for feature set
132aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    DebugCommand(wifi_interface_handle iface, unsigned int *support, GetCmdType cmdType)
133d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        : WifiCommand("DebugCommand", iface, 0), mSupport(support), mType(cmdType)
134aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    { }
135aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
136aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    // constructor for ring params
137aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    DebugCommand(wifi_interface_handle iface, u32 verbose_level, u32 flags,
138aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            u32 max_interval_sec, u32 min_data_size, char *ring_name, GetCmdType cmdType)
139d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        : WifiCommand("DebugCommand", iface, 0), mVerboseLevel(verbose_level), mFlags(flags),
140aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        mMaxIntervalSec(max_interval_sec), mMinDataSize(min_data_size),
141aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        mRingName(ring_name), mType(cmdType)
142aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    { }
143aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
144aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    int createRingRequest(WifiRequest& request) {
145aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        int result = request.create(GOOGLE_OUI, LOGGER_START_LOGGING);
146aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        if (result != WIFI_SUCCESS) {
147aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            ALOGE("Failed to create start ring logger request; result = %d", result);
148aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            return result;
149aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        }
150aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
151aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
152aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
153aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        result = request.put_u32(LOGGER_ATTRIBUTE_LOG_LEVEL, mVerboseLevel);
154aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        if (result != WIFI_SUCCESS) {
155aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            ALOGE("Failed to put log level; result = %d", result);
156aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            return result;
157aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        }
158aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        result = request.put_u32(LOGGER_ATTRIBUTE_RING_FLAGS, mFlags);
159aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        if (result != WIFI_SUCCESS) {
160aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            ALOGE("Failed to put ring flags; result = %d", result);
161aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            return result;
162aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        }
163aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        result = request.put_u32(LOGGER_ATTRIBUTE_LOG_TIME_INTVAL, mMaxIntervalSec);
164aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        if (result != WIFI_SUCCESS) {
165aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            ALOGE("Failed to put log time interval; result = %d", result);
166aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            return result;
167aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        }
168aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        result = request.put_u32(LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE, mMinDataSize);
169aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        if (result != WIFI_SUCCESS) {
170aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            ALOGE("Failed to put min data size; result = %d", result);
171aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            return result;
172aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        }
173aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        result = request.put_string(LOGGER_ATTRIBUTE_RING_NAME, mRingName);
174aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        if (result != WIFI_SUCCESS) {
175aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            ALOGE("Failed to put ringbuffer name; result = %d", result);
176aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            return result;
177aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        }
178aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        request.attr_end(data);
179aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
180aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        return WIFI_SUCCESS;
181aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    }
182aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
183aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    int createRequest(WifiRequest &request) {
184aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        int result;
185aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
186aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        switch (mType) {
187aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            case GET_FW_VER:
188aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            {
189aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                result = request.create(GOOGLE_OUI, LOGGER_GET_VER);
190aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (result != WIFI_SUCCESS) {
191aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    ALOGE("Failed to create get fw version request; result = %d", result);
192aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    return result;
193aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                }
194aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
195aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
196aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
197aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                // Driver expecting only attribute type, passing mbuff as data with
198aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                // length 0 to avoid undefined state
199040ee11fb7c5f1781537ae4343c056c0a49dcfc5xinhe                result = request.put(LOGGER_ATTRIBUTE_FW_VER, mBuff, 0);
200aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (result != WIFI_SUCCESS) {
201aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    ALOGE("Failed to put get fw version request; result = %d", result);
202aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    return result;
203aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                }
204aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                request.attr_end(data);
205aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                break;
206aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            }
207aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
208aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            case GET_DRV_VER:
209aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            {
210aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                result = request.create(GOOGLE_OUI, LOGGER_GET_VER);
211aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (result != WIFI_SUCCESS) {
212aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    ALOGE("Failed to create get drv version request; result = %d", result);
213aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    return result;
214aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                }
215aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
216aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
217aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
218aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                // Driver expecting only attribute type, passing mbuff as data with
219aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                // length 0 to avoid undefined state
220040ee11fb7c5f1781537ae4343c056c0a49dcfc5xinhe                result = request.put(LOGGER_ATTRIBUTE_DRIVER_VER, mBuff, 0);
221aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
222aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (result != WIFI_SUCCESS) {
223aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    ALOGE("Failed to put get drv version request; result = %d", result);
224aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    return result;
225aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                }
226aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                request.attr_end(data);
227aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                break;
228aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            }
229aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
230aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            case GET_RING_DATA:
231aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            {
232aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                result = request.create(GOOGLE_OUI, LOGGER_GET_RING_DATA);
233aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (result != WIFI_SUCCESS) {
234aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    ALOGE("Failed to create get ring data request; result = %d", result);
235aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    return result;
236aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                }
237aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
238aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
239aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                result = request.put_string(LOGGER_ATTRIBUTE_RING_NAME, mRingName);
240aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (result != WIFI_SUCCESS) {
241aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    ALOGE("Failed to put ring data request; result = %d", result);
242aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    return result;
243aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                }
244aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                request.attr_end(data);
245aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                break;
246aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            }
247aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
248aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            case GET_RING_STATUS:
249aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            {
250aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                result = request.create(GOOGLE_OUI, LOGGER_GET_RING_STATUS);
251aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (result != WIFI_SUCCESS) {
252aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    ALOGE("Failed to create get ring status request; result = %d", result);
253aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    return result;
254aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                }
255aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                break;
256aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            }
257aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
258aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            case GET_FEATURE:
259aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            {
260aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                result = request.create(GOOGLE_OUI, LOGGER_GET_FEATURE);
261aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (result != WIFI_SUCCESS) {
262aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    ALOGE("Failed to create get feature request; result = %d", result);
263aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    return result;
264aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                }
265aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                break;
266aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            }
267aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
268aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            case START_RING_LOG:
269aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                result = createRingRequest(request);
270aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                break;
271aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
272aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            default:
273aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                ALOGE("Unknown Debug command");
274aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                result = WIFI_ERROR_UNKNOWN;
275aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        }
276aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        return result;
277aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    }
278aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
279aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    int start() {
280bedc792622bd9ef90c30e4d8c5efa194f1010d2eVinit Deshpande        // ALOGD("Start debug command");
281aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        WifiRequest request(familyId(), ifaceId());
282aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        int result = createRequest(request);
283aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        if (result != WIFI_SUCCESS) {
284aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            ALOGE("Failed to create debug request; result = %d", result);
285aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            return result;
286aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        }
287aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
288aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        result = requestResponse(request);
289aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        if (result != WIFI_SUCCESS) {
290aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            ALOGE("Failed to register debug response; result = %d", result);
291aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        }
292aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        return result;
293aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    }
294aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
295aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    virtual int handleResponse(WifiEvent& reply) {
296aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        ALOGD("In DebugCommand::handleResponse");
297aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
298aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        if (reply.get_cmd() != NL80211_CMD_VENDOR) {
299aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
300aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            return NL_SKIP;
301aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        }
302aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
303aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        switch (mType) {
304aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            case GET_DRV_VER:
305aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            case GET_FW_VER:
306aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            {
307aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                void *data = reply.get_vendor_data();
308aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                int len = reply.get_vendor_data_len();
309aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
310aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                ALOGD("len = %d, expected len = %d", len, *mBuffSize);
311040ee11fb7c5f1781537ae4343c056c0a49dcfc5xinhe                memcpy(mBuff, data, min(len, *mBuffSize));
312aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (*mBuffSize < len)
313aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    return NL_SKIP;
314aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                *mBuffSize = len;
315aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                break;
316aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            }
317aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
318aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            case START_RING_LOG:
319aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            case GET_RING_DATA:
320aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                break;
321aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
322aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            case GET_RING_STATUS:
323aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            {
324aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
325aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                int len = reply.get_vendor_data_len();
326040ee11fb7c5f1781537ae4343c056c0a49dcfc5xinhe                wifi_ring_buffer_status *status(mStatus);
327aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
328aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (vendor_data == NULL || len == 0) {
329aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    ALOGE("No Debug data found");
330aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    return NL_SKIP;
331aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                }
332aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
333aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                nl_iterator it(vendor_data);
334aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (it.get_type() == LOGGER_ATTRIBUTE_RING_NUM) {
335aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    unsigned int num_rings = it.get_u32();
336aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    if (*mNumRings < num_rings) {
337aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                        ALOGE("Not enough status buffers provided, available: %d required: %d",
338aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                                *mNumRings, num_rings);
339aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    } else {
340aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                        *mNumRings = num_rings;
341aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    }
342aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                } else {
343aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    ALOGE("Unknown attribute: %d expecting %d",
344aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                            it.get_type(), LOGGER_ATTRIBUTE_RING_NUM);
345aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    return NL_SKIP;
346aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                }
347aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
348aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                it.next();
349aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                for (unsigned int i = 0; it.has_next() && i < *mNumRings; it.next()) {
350aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    if (it.get_type() == LOGGER_ATTRIBUTE_RING_STATUS) {
351aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                        memcpy(status, it.get_data(), sizeof(wifi_ring_buffer_status));
352aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                        i++;
353aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                        status++;
354aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    } else {
355aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                        ALOGW("Ignoring invalid attribute type = %d, size = %d",
356aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                                it.get_type(), it.get_len());
357aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    }
358aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                }
359aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                break;
360aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            }
361aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
362aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            case GET_FEATURE:
363aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            {
364aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                void *data = reply.get_vendor_data();
365aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                int len = reply.get_vendor_data_len();
366aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
367aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                ALOGD("len = %d, expected len = %d", len, sizeof(unsigned int));
368aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                memcpy(mSupport, data, sizeof(unsigned int));
369aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                break;
370aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            }
371aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
372aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            default:
373aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                ALOGW("Unknown Debug command");
374aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        }
375aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        return NL_OK;
376aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    }
377aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
378aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    virtual int handleEvent(WifiEvent& event) {
379aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        /* NO events! */
380aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        return NL_SKIP;
381aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    }
382aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee};
383aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
384aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee/* API to collect a firmware version string */
385040ee11fb7c5f1781537ae4343c056c0a49dcfc5xinhewifi_error wifi_get_firmware_version(wifi_interface_handle iface, char *buffer,
386040ee11fb7c5f1781537ae4343c056c0a49dcfc5xinhe        int buffer_size)
387aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee{
388040ee11fb7c5f1781537ae4343c056c0a49dcfc5xinhe    if (buffer && (buffer_size > 0)) {
389040ee11fb7c5f1781537ae4343c056c0a49dcfc5xinhe        DebugCommand *cmd = new DebugCommand(iface, buffer, &buffer_size, GET_FW_VER);
3906af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
3916af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        wifi_error result = (wifi_error)cmd->start();
3926af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        cmd->releaseRef();
3936af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        return result;
394aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    } else {
395aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        ALOGE("FW version buffer NULL");
396aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        return  WIFI_ERROR_INVALID_ARGS;
397aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    }
398aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee}
399aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
400aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee/* API to collect a driver version string */
401040ee11fb7c5f1781537ae4343c056c0a49dcfc5xinhewifi_error wifi_get_driver_version(wifi_interface_handle iface, char *buffer, int buffer_size)
402aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee{
403040ee11fb7c5f1781537ae4343c056c0a49dcfc5xinhe    if (buffer && (buffer_size > 0)) {
404040ee11fb7c5f1781537ae4343c056c0a49dcfc5xinhe        DebugCommand *cmd = new DebugCommand(iface, buffer, &buffer_size, GET_DRV_VER);
4056af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
4066af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        wifi_error result = (wifi_error)cmd->start();
4076af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        cmd->releaseRef();
4086af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        return result;
409aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    } else {
410aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        ALOGE("Driver version buffer NULL");
411aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        return  WIFI_ERROR_INVALID_ARGS;
412aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    }
413aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee}
414aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
415aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee/* API to collect driver records */
416aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Leewifi_error wifi_get_ring_data(wifi_interface_handle iface, char *ring_name)
417aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee{
418aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    DebugCommand *cmd = new DebugCommand(iface, ring_name, GET_RING_DATA);
4196af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
4206af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    wifi_error result = (wifi_error)cmd->start();
4216af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    cmd->releaseRef();
4226af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    return result;
423aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee}
424aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
425aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee/* API to get the status of all ring buffers supported by driver */
426aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Leewifi_error wifi_get_ring_buffers_status(wifi_interface_handle iface,
427040ee11fb7c5f1781537ae4343c056c0a49dcfc5xinhe        u32 *num_rings, wifi_ring_buffer_status *status)
428aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee{
429040ee11fb7c5f1781537ae4343c056c0a49dcfc5xinhe    if (status && num_rings) {
430aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        DebugCommand *cmd = new DebugCommand(iface, num_rings, status, GET_RING_STATUS);
4316af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
4326af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        wifi_error result = (wifi_error)cmd->start();
4336af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        cmd->releaseRef();
4346af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        return result;
435aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    } else {
436aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        ALOGE("Ring status buffer NULL");
437aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        return  WIFI_ERROR_INVALID_ARGS;
438aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    }
439aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee}
440aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
441aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee/* API to get supportable feature */
442aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Leewifi_error wifi_get_logger_supported_feature_set(wifi_interface_handle iface,
443aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        unsigned int *support)
444aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee{
445aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    if (support) {
446aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        DebugCommand *cmd = new DebugCommand(iface, support, GET_FEATURE);
4476af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
4486af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        wifi_error result = (wifi_error)cmd->start();
4496af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        cmd->releaseRef();
4506af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        return result;
451aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    } else {
452aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        ALOGE("Get support buffer NULL");
453aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        return  WIFI_ERROR_INVALID_ARGS;
454aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    }
455aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee}
456aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
457aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Leewifi_error wifi_start_logging(wifi_interface_handle iface, u32 verbose_level,
458aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        u32 flags, u32 max_interval_sec, u32 min_data_size, char *ring_name)
459aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee{
460aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    if (ring_name) {
4616af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        DebugCommand *cmd = new DebugCommand(iface, verbose_level, flags, max_interval_sec,
4626af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma                    min_data_size, ring_name, START_RING_LOG);
4636af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
4646af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        wifi_error result = (wifi_error)cmd->start();
4656af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        cmd->releaseRef();
4666af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        return result;
467aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    } else {
468aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        ALOGE("Ring name NULL");
469aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        return  WIFI_ERROR_INVALID_ARGS;
470aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    }
471aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee}
472aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
473aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
474aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee///////////////////////////////////////////////////////////////////////////////
475aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Leeclass SetLogHandler : public WifiCommand
476aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee{
477aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    wifi_ring_buffer_data_handler mHandler;
478aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
479aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Leepublic:
480aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    SetLogHandler(wifi_interface_handle iface, int id, wifi_ring_buffer_data_handler handler)
481d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        : WifiCommand("SetLogHandler", iface, id), mHandler(handler)
482aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    { }
483aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
484aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    int start() {
48556deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee        ALOGV("Register loghandler");
486aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        registerVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_RING_EVENT);
487aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        return WIFI_SUCCESS;
488aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    }
489aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
4905ca0ce0387ccaa71c18c09278bf8d810759c3aa9Vinit Deshpande    virtual int cancel() {
491c604b53461cfea0a1e6f6f5ad84b0a35be69b8e0JerryLee        /* Send a command to driver to stop generating logging events */
49256deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee        ALOGV("Clear loghandler");
493c604b53461cfea0a1e6f6f5ad84b0a35be69b8e0JerryLee
494f02f545dd490b658110fb837f4905050b3ed9c52Vinit Deshpande        /* unregister event handler */
495f02f545dd490b658110fb837f4905050b3ed9c52Vinit Deshpande        unregisterVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_RING_EVENT);
496f02f545dd490b658110fb837f4905050b3ed9c52Vinit Deshpande
497c604b53461cfea0a1e6f6f5ad84b0a35be69b8e0JerryLee        WifiRequest request(familyId(), ifaceId());
498c604b53461cfea0a1e6f6f5ad84b0a35be69b8e0JerryLee        int result = request.create(GOOGLE_OUI, LOGGER_RESET_LOGGING);
499c604b53461cfea0a1e6f6f5ad84b0a35be69b8e0JerryLee        if (result != WIFI_SUCCESS) {
500c604b53461cfea0a1e6f6f5ad84b0a35be69b8e0JerryLee            ALOGE("failed to create reset request; result = %d", result);
501c604b53461cfea0a1e6f6f5ad84b0a35be69b8e0JerryLee            return result;
502c604b53461cfea0a1e6f6f5ad84b0a35be69b8e0JerryLee        }
503c604b53461cfea0a1e6f6f5ad84b0a35be69b8e0JerryLee
504c604b53461cfea0a1e6f6f5ad84b0a35be69b8e0JerryLee        result = requestResponse(request);
505c604b53461cfea0a1e6f6f5ad84b0a35be69b8e0JerryLee        if (result != WIFI_SUCCESS) {
506c604b53461cfea0a1e6f6f5ad84b0a35be69b8e0JerryLee            ALOGE("failed to request reset; result = %d", result);
507c604b53461cfea0a1e6f6f5ad84b0a35be69b8e0JerryLee            return result;
508c604b53461cfea0a1e6f6f5ad84b0a35be69b8e0JerryLee        }
5095ca0ce0387ccaa71c18c09278bf8d810759c3aa9Vinit Deshpande
51056deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee        ALOGD("Success to clear loghandler");
5115ca0ce0387ccaa71c18c09278bf8d810759c3aa9Vinit Deshpande        return WIFI_SUCCESS;
5125ca0ce0387ccaa71c18c09278bf8d810759c3aa9Vinit Deshpande    }
5135ca0ce0387ccaa71c18c09278bf8d810759c3aa9Vinit Deshpande
514aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    virtual int handleEvent(WifiEvent& event) {
515aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        char *buffer = NULL;
516aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        int buffer_size = 0;
517aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
518bedc792622bd9ef90c30e4d8c5efa194f1010d2eVinit Deshpande        // ALOGD("In SetLogHandler::handleEvent");
519aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
520aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        int len = event.get_vendor_data_len();
521aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        int event_id = event.get_vendor_subcmd();
522bedc792622bd9ef90c30e4d8c5efa194f1010d2eVinit Deshpande        // ALOGI("Got Logger event: %d", event_id);
523aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
524aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        if (vendor_data == NULL || len == 0) {
525aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            ALOGE("No Debug data found");
526aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            return NL_SKIP;
527aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        }
528aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
529aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        if(event_id == GOOGLE_DEBUG_RING_EVENT) {
530aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            wifi_ring_buffer_status status;
531aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            memset(&status, 0, sizeof(status));
532aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
533aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
534aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (it.get_type() == LOGGER_ATTRIBUTE_RING_STATUS) {
535aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    memcpy(&status, it.get_data(), sizeof(status));
536aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                } else if (it.get_type() == LOGGER_ATTRIBUTE_RING_DATA) {
537aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    buffer_size = it.get_len();
538aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    buffer = (char *)it.get_data();
539aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                } else {
540aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    ALOGW("Ignoring invalid attribute type = %d, size = %d",
541aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                            it.get_type(), it.get_len());
542aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                }
543aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            }
544aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
545bedc792622bd9ef90c30e4d8c5efa194f1010d2eVinit Deshpande            // ALOGI("Retrieved Debug data");
546aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            if (mHandler.on_ring_buffer_data) {
547aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                (*mHandler.on_ring_buffer_data)((char *)status.name, buffer, buffer_size,
548aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                        &status);
549aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            }
550aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        } else {
551aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            ALOGE("Unknown Event");
552aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            return NL_SKIP;
553aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        }
554aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        return NL_OK;
555aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    }
556aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee};
557aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
558aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Leewifi_error wifi_set_log_handler(wifi_request_id id, wifi_interface_handle iface,
559aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        wifi_ring_buffer_data_handler handler)
560aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee{
561aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    wifi_handle handle = getWifiHandle(iface);
56256deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee    ALOGV("Loghandler start, handle = %p", handle);
563aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
56456deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee    SetLogHandler *cmd = new SetLogHandler(iface, id, handler);
5656af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
5666af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    wifi_error result = wifi_register_cmd(handle, id, cmd);
5676af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    if (result != WIFI_SUCCESS) {
5686af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        cmd->releaseRef();
5696af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        return result;
5706af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    }
5716af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    result = (wifi_error)cmd->start();
5726af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    if (result != WIFI_SUCCESS) {
5736af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        wifi_unregister_cmd(handle, id);
5746af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        cmd->releaseRef();
57556deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee        return result;
576aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    }
5776af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    return result;
578aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee}
579aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
580c604b53461cfea0a1e6f6f5ad84b0a35be69b8e0JerryLeewifi_error wifi_reset_log_handler(wifi_request_id id, wifi_interface_handle iface)
581c604b53461cfea0a1e6f6f5ad84b0a35be69b8e0JerryLee{
582c604b53461cfea0a1e6f6f5ad84b0a35be69b8e0JerryLee    wifi_handle handle = getWifiHandle(iface);
58356deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee    ALOGV("Loghandler reset, wifi_request_id = %d, handle = %p", id, handle);
584c604b53461cfea0a1e6f6f5ad84b0a35be69b8e0JerryLee
58556deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee    if (id == -1) {
58656deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee        wifi_ring_buffer_data_handler handler;
58756deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee        memset(&handler, 0, sizeof(handler));
58856deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee
58956deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee        SetLogHandler *cmd = new SetLogHandler(iface, id, handler);
5906af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
591c604b53461cfea0a1e6f6f5ad84b0a35be69b8e0JerryLee        cmd->cancel();
592c604b53461cfea0a1e6f6f5ad84b0a35be69b8e0JerryLee        cmd->releaseRef();
593c604b53461cfea0a1e6f6f5ad84b0a35be69b8e0JerryLee        return WIFI_SUCCESS;
594c604b53461cfea0a1e6f6f5ad84b0a35be69b8e0JerryLee    }
59556deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee
59656deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee    return wifi_cancel_cmd(id, iface);
597c604b53461cfea0a1e6f6f5ad84b0a35be69b8e0JerryLee}
598c604b53461cfea0a1e6f6f5ad84b0a35be69b8e0JerryLee
599aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee///////////////////////////////////////////////////////////////////////////////
600aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Leeclass SetAlertHandler : public WifiCommand
601aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee{
602aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    wifi_alert_handler mHandler;
603aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    int mBuffSize;
604aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    char *mBuff;
605aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    int mErrCode;
606aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
607aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Leepublic:
608aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    SetAlertHandler(wifi_interface_handle iface, int id, wifi_alert_handler handler)
609d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        : WifiCommand("SetAlertHandler", iface, id), mHandler(handler), mBuffSize(0), mBuff(NULL),
610d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande            mErrCode(0)
611aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    { }
612aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
613aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    int start() {
61456deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee        ALOGV("Start Alerting");
615aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        registerVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_MEM_DUMP_EVENT);
616aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        return WIFI_SUCCESS;
617aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    }
618aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
61956deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee    virtual int cancel() {
62056deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee        ALOGV("Clear alerthandler");
62156deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee
62256deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee        /* unregister alert handler */
62356deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee        unregisterVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_MEM_DUMP_EVENT);
62456deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee        wifi_unregister_cmd(wifiHandle(), id());
62556deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee        ALOGD("Success to clear alerthandler");
62656deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee        return WIFI_SUCCESS;
62756deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee    }
62856deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee
629aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    virtual int handleResponse(WifiEvent& reply) {
630aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        ALOGD("In SetAlertHandler::handleResponse");
631aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
632aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        if (reply.get_cmd() != NL80211_CMD_VENDOR) {
633aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
634aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            return NL_SKIP;
635aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        }
636aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
637aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
638aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        int len = reply.get_vendor_data_len();
639aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
640aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        ALOGD("len = %d", len);
641aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        if (vendor_data == NULL || len == 0) {
642aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            ALOGE("no vendor data in memory dump response; ignoring it");
643aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            return NL_SKIP;
644aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        }
645aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
646aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
647aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            if (it.get_type() == LOGGER_ATTRIBUTE_FW_DUMP_DATA) {
648aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                ALOGI("Initiating alert callback");
649aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (mHandler.on_alert) {
650aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    (*mHandler.on_alert)(id(), mBuff, mBuffSize, mErrCode);
651aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                }
652aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (mBuff) {
653aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    free(mBuff);
654aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    mBuff = NULL;
655aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                }
656aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            }
657aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        }
658aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        return NL_OK;
659aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    }
660aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
661aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    virtual int handleEvent(WifiEvent& event) {
662aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        wifi_ring_buffer_id ring_id;
663aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        char *buffer = NULL;
664aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        int buffer_size = 0;
665aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
666aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
667aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
668aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        int len = event.get_vendor_data_len();
669aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        int event_id = event.get_vendor_subcmd();
670aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        ALOGI("Got event: %d", event_id);
671aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
672aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        if (vendor_data == NULL || len == 0) {
673aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            ALOGE("No Debug data found");
674aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            return NL_SKIP;
675aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        }
676aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
677aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        if (event_id == GOOGLE_DEBUG_MEM_DUMP_EVENT) {
678aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
679aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (it.get_type() == LOGGER_ATTRIBUTE_FW_DUMP_LEN) {
680aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    mBuffSize = it.get_u32();
681aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                } else if (it.get_type() == LOGGER_ATTRIBUTE_RING_DATA) {
682aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    buffer_size = it.get_len();
683aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    buffer = (char *)it.get_data();
684aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            /*
685aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                } else if (it.get_type() == LOGGER_ATTRIBUTE_FW_ERR_CODE) {
686aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    mErrCode = it.get_u32();
687aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            */
688aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                } else {
689aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    ALOGW("Ignoring invalid attribute type = %d, size = %d",
690aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                            it.get_type(), it.get_len());
691aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                }
692aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            }
693aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            if (mBuffSize) {
694aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                ALOGD("dump size: %d meta data size: %d", mBuffSize, buffer_size);
695aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (mBuff) free(mBuff);
696aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                mBuff = (char *)malloc(mBuffSize + buffer_size);
697aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (!mBuff) {
698aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    ALOGE("Buffer allocation failed");
699aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    return NL_SKIP;
700aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                }
701aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                memcpy(mBuff, buffer, buffer_size);
702aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
703aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                WifiRequest request(familyId(), ifaceId());
704aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                int result = request.create(GOOGLE_OUI, LOGGER_GET_MEM_DUMP);
705aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (result != WIFI_SUCCESS) {
706aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    ALOGE("Failed to create get memory dump request; result = %d", result);
707aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    free(mBuff);
708aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    return NL_SKIP;
709aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                }
710aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
711aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                result = request.put_u32(LOGGER_ATTRIBUTE_FW_DUMP_LEN, mBuffSize);
712aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (result != WIFI_SUCCESS) {
713aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    ALOGE("Failed to put get memory dump request; result = %d", result);
714aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    return result;
715aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                }
716b3b31174c61e38a970b956cb50cb66cd1903ca9bJerry Lee
717b3b31174c61e38a970b956cb50cb66cd1903ca9bJerry Lee                result = request.put_u64(LOGGER_ATTRIBUTE_FW_DUMP_DATA,
718b3b31174c61e38a970b956cb50cb66cd1903ca9bJerry Lee                         (uint64_t)(mBuff+buffer_size));
719aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (result != WIFI_SUCCESS) {
720aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    ALOGE("Failed to put get memory dump request; result = %d", result);
721aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    return result;
722aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                }
723865ee9aa73c86404aa1ec3895a0a828a2b888ec5xinhe
724aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                request.attr_end(data);
725aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                mBuffSize += buffer_size;
726aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
727aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                result = requestResponse(request);
728aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
729aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (result != WIFI_SUCCESS) {
730aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    ALOGE("Failed to register get momory dump response; result = %d", result);
731aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                }
732aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            } else {
733aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                ALOGE("dump event missing dump length attribute");
734aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                return NL_SKIP;
735aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            }
736aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        }
737aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        return NL_OK;
738aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    }
739aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee};
740aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
741aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Leewifi_error wifi_set_alert_handler(wifi_request_id id, wifi_interface_handle iface,
742aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        wifi_alert_handler handler)
743aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee{
744aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    wifi_handle handle = getWifiHandle(iface);
74556deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee    ALOGV("Alerthandler start, handle = %p", handle);
74656deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee
747aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    SetAlertHandler *cmd = new SetAlertHandler(iface, id, handler);
7486af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
7496af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    wifi_error result = wifi_register_cmd(handle, id, cmd);
7506af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    if (result != WIFI_SUCCESS) {
7516af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        cmd->releaseRef();
7526af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        return result;
7536af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    }
7546af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    result = (wifi_error)cmd->start();
7556af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    if (result != WIFI_SUCCESS) {
7566af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        wifi_unregister_cmd(handle, id);
7576af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        cmd->releaseRef();
75856deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee        return result;
75956deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee    }
7606af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    return result;
761aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee}
762aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
76356deba26a624507fc2e0e6b134f8bd88d091a141Jerry Leewifi_error wifi_reset_alert_handler(wifi_request_id id, wifi_interface_handle iface)
76456deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee{
76556deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee    wifi_handle handle = getWifiHandle(iface);
76656deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee    ALOGV("Alerthandler reset, wifi_request_id = %d, handle = %p", id, handle);
76756deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee
76856deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee    if (id == -1) {
76956deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee        wifi_alert_handler handler;
77056deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee        memset(&handler, 0, sizeof(handler));
77156deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee
77256deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee        SetAlertHandler *cmd = new SetAlertHandler(iface, id, handler);
7736af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
77456deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee        cmd->cancel();
77556deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee        cmd->releaseRef();
77656deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee        return WIFI_SUCCESS;
77756deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee    }
77856deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee
77956deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee    return wifi_cancel_cmd(id, iface);
78056deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee}
781aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
782aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee///////////////////////////////////////////////////////////////////////////////
783aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Leeclass MemoryDumpCommand: public WifiCommand
784aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee{
785aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    wifi_firmware_memory_dump_handler mHandler;
786aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    int mBuffSize;
787aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    char *mBuff;
788aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
789aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Leepublic:
790aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    MemoryDumpCommand(wifi_interface_handle iface, wifi_firmware_memory_dump_handler handler)
791d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        : WifiCommand("MemoryDumpCommand", iface, 0), mHandler(handler), mBuffSize(0), mBuff(NULL)
792aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    { }
793aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
794aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    int start() {
795aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        ALOGD("Start memory dump command");
796aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        WifiRequest request(familyId(), ifaceId());
797aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
798aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        int result = request.create(GOOGLE_OUI, LOGGER_TRIGGER_MEM_DUMP);
799aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        if (result != WIFI_SUCCESS) {
800aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            ALOGE("Failed to create trigger fw memory dump request; result = %d", result);
801aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            return result;
802aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        }
803aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
804aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        result = requestResponse(request);
805aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        if (result != WIFI_SUCCESS) {
806aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            ALOGE("Failed to register trigger memory dump response; result = %d", result);
807aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        }
808aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        return result;
809aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    }
810aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
811aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    virtual int handleResponse(WifiEvent& reply) {
812aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        ALOGD("In MemoryDumpCommand::handleResponse");
813aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
814aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        if (reply.get_cmd() != NL80211_CMD_VENDOR) {
815aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
816aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            return NL_SKIP;
817aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        }
818aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
819aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
820aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        int len = reply.get_vendor_data_len();
821aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
822aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        ALOGD("len = %d", len);
823aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        if (vendor_data == NULL || len == 0) {
824aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            ALOGE("no vendor data in memory dump response; ignoring it");
825aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            return NL_SKIP;
826aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        }
827aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
828aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
829aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            if (it.get_type() == LOGGER_ATTRIBUTE_FW_DUMP_LEN) {
830aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                mBuffSize = it.get_u32();
831aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
832aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (mBuff)
833aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    free(mBuff);
834aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                mBuff = (char *)malloc(mBuffSize);
835aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (!mBuff) {
836aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    ALOGE("Buffer allocation failed");
837aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    return NL_SKIP;
838aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                }
839aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                WifiRequest request(familyId(), ifaceId());
840aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                int result = request.create(GOOGLE_OUI, LOGGER_GET_MEM_DUMP);
841aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (result != WIFI_SUCCESS) {
842aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    ALOGE("Failed to create get memory dump request; result = %d", result);
843aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    free(mBuff);
844aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    return NL_SKIP;
845aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                }
846aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
847aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
848aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                result = request.put_u32(LOGGER_ATTRIBUTE_FW_DUMP_LEN, mBuffSize);
849aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (result != WIFI_SUCCESS) {
850aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    ALOGE("Failed to put get memory dump request; result = %d", result);
851aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    return result;
852aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                }
853b3b31174c61e38a970b956cb50cb66cd1903ca9bJerry Lee
854b3b31174c61e38a970b956cb50cb66cd1903ca9bJerry Lee                result = request.put_u64(LOGGER_ATTRIBUTE_FW_DUMP_DATA, (uint64_t)mBuff);
855aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (result != WIFI_SUCCESS) {
856aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    ALOGE("Failed to put get memory dump request; result = %d", result);
857aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    return result;
858aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                }
859aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                request.attr_end(data);
860aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
861aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                result = requestResponse(request);
862aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (result != WIFI_SUCCESS) {
863aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    ALOGE("Failed to register get momory dump response; result = %d", result);
864aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                }
865aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            } else if (it.get_type() == LOGGER_ATTRIBUTE_FW_DUMP_DATA) {
866aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                ALOGI("Initiating memory dump callback");
867aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (mHandler.on_firmware_memory_dump) {
868aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    (*mHandler.on_firmware_memory_dump)(mBuff, mBuffSize);
869aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                }
870aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                if (mBuff) {
871aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    free(mBuff);
872aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                    mBuff = NULL;
873aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                }
874aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            } else {
875aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                ALOGW("Ignoring invalid attribute type = %d, size = %d",
876aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee                        it.get_type(), it.get_len());
877aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee            }
878aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        }
879aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        return NL_OK;
880aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    }
881aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
882aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    virtual int handleEvent(WifiEvent& event) {
883aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        /* NO events! */
884aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        return NL_SKIP;
885aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    }
886aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee};
887aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
888aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee/* API to collect a firmware memory dump for a given iface */
889aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Leewifi_error wifi_get_firmware_memory_dump( wifi_interface_handle iface,
890aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee        wifi_firmware_memory_dump_handler handler)
891aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee{
892aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee    MemoryDumpCommand *cmd = new MemoryDumpCommand(iface, handler);
8936af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
8946af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    wifi_error result = (wifi_error)cmd->start();
8956af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    cmd->releaseRef();
8966af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    return result;
897aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee}
898aa306e5f46b3e0e72d7917760b8af6aaebc35b1eJerry Lee
8997e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharmaclass PacketFateCommand: public WifiCommand
9007e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma{
9017e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    void *mReportBufs;
9027e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    size_t mNoReqFates;
9037e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    size_t *mNoProvidedFates;
9047e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    PktFateReqType mReqType;
9057e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma
9067e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharmapublic:
9077e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    PacketFateCommand(wifi_interface_handle handle)
9087e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        : WifiCommand("PacketFateCommand", handle, 0), mReqType(PACKET_MONITOR_START)
9097e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    { }
9107e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma
9117e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    PacketFateCommand(wifi_interface_handle handle, wifi_tx_report *tx_report_bufs,
9127e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            size_t n_requested_fates, size_t *n_provided_fates)
9137e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        : WifiCommand("PacketFateCommand", handle, 0), mReportBufs(tx_report_bufs),
9147e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma                  mNoReqFates(n_requested_fates), mNoProvidedFates(n_provided_fates),
9157e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma                  mReqType(TX_PACKET_FATE)
9167e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    { }
9177e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma
9187e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    PacketFateCommand(wifi_interface_handle handle, wifi_rx_report *rx_report_bufs,
9197e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            size_t n_requested_fates, size_t *n_provided_fates)
9207e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        : WifiCommand("PacketFateCommand", handle, 0), mReportBufs(rx_report_bufs),
9217e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma                  mNoReqFates(n_requested_fates), mNoProvidedFates(n_provided_fates),
9227e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma                  mReqType(RX_PACKET_FATE)
9237e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    { }
9247e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma
9257e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    int createRequest(WifiRequest& request) {
9267e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        if (mReqType == TX_PACKET_FATE) {
9277e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            ALOGD("%s Get Tx packet fate request\n", __FUNCTION__);
9287e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            return createTxPktFateRequest(request);
9297e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        } else if (mReqType == RX_PACKET_FATE) {
9307e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            ALOGD("%s Get Rx packet fate request\n", __FUNCTION__);
9317e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            return createRxPktFateRequest(request);
9327e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        } else if (mReqType == PACKET_MONITOR_START) {
9337e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            ALOGD("%s Monitor packet fate request\n", __FUNCTION__);
9347e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            return createMonitorPktFateRequest(request);
9357e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        } else {
9367e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            ALOGE("%s Unknown packet fate request\n", __FUNCTION__);
9377e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            return WIFI_ERROR_NOT_SUPPORTED;
9387e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        }
9397e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        return WIFI_SUCCESS;
9407e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    }
9417e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma
9427e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    int createMonitorPktFateRequest(WifiRequest& request) {
9437e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        int result = request.create(GOOGLE_OUI, LOGGER_START_PKT_FATE_MONITORING);
9447e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        if (result < 0) {
9457e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            return result;
9467e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        }
9477e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma
9487e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
9497e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        request.attr_end(data);
9507e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        return result;
9517e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    }
9527e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma
9537e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    int createTxPktFateRequest(WifiRequest& request) {
9547e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        int result = request.create(GOOGLE_OUI, LOGGER_GET_TX_PKT_FATES);
9557e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        if (result < 0) {
9567e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            return result;
9577e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        }
9587e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma
9597e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        memset(mReportBufs, 0, (mNoReqFates * sizeof(wifi_tx_report)));
9607e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
9617e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        result = request.put_u32(LOGGER_ATTRIBUTE_PKT_FATE_NUM, mNoReqFates);
9627e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        if (result < 0) {
9637e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            return result;
9647e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        }
9657e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        result = request.put_u64(LOGGER_ATTRIBUTE_PKT_FATE_DATA, (uint64_t)mReportBufs);
9667e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        if (result < 0) {
9677e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            return result;
9687e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        }
9697e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        request.attr_end(data);
9707e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        return result;
9717e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    }
9727e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma
9737e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    int createRxPktFateRequest(WifiRequest& request) {
9747e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        int result = request.create(GOOGLE_OUI, LOGGER_GET_RX_PKT_FATES);
9757e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        if (result < 0) {
9767e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            return result;
9777e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        }
9787e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma
9797e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        memset(mReportBufs, 0, (mNoReqFates * sizeof(wifi_rx_report)));
9807e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
9817e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        result = request.put_u32(LOGGER_ATTRIBUTE_PKT_FATE_NUM, mNoReqFates);
9827e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        if (result < 0) {
9837e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            return result;
9847e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        }
9857e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        result = request.put_u64(LOGGER_ATTRIBUTE_PKT_FATE_DATA, (uint64_t)mReportBufs);
9867e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        if (result < 0) {
9877e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            return result;
9887e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        }
9897e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        request.attr_end(data);
9907e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        return result;
9917e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    }
9927e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma
9937e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    int start() {
9947e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        ALOGD("Start get packet fate command\n");
9957e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        WifiRequest request(familyId(), ifaceId());
9967e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma
9977e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        int result = createRequest(request);
9987e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        if (result < 0) {
9997e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            ALOGE("Failed to create get pkt fate request; result = %d\n", result);
10007e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            return result;
10017e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        }
10027e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma
10037e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        result = requestResponse(request);
10047e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        if (result != WIFI_SUCCESS) {
10057e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            ALOGE("Failed to register get pkt fate response; result = %d\n", result);
10067e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        }
10077e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        return result;
10087e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    }
10097e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma
10107e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    int handleResponse(WifiEvent& reply) {
10117e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        ALOGD("In GetPktFateCommand::handleResponse\n");
10127e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma
10137e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        if (reply.get_cmd() != NL80211_CMD_VENDOR) {
10147e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            ALOGI("Ignoring reply with cmd = %d", reply.get_cmd());
10157e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            return NL_SKIP;
10167e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        }
10177e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma
10187e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        int id = reply.get_vendor_id();
10197e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        int subcmd = reply.get_vendor_subcmd();
10207e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
10217e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        int len = reply.get_vendor_data_len();
10227e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma
10237e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        ALOGI("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
10247e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma
10257e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        if (mReqType == TX_PACKET_FATE) {
10266af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma            ALOGI("Response recieved for get TX pkt fate command\n");
10277e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        } else if (mReqType == RX_PACKET_FATE) {
10286af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma            ALOGI("Response recieved for get RX pkt fate command\n");
10297e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        } else if (mReqType == PACKET_MONITOR_START) {
10306af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma            ALOGI("Response recieved for monitor pkt fate command\n");
10317e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            return NL_OK;
10327e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        } else {
10336af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma            ALOGE("Response recieved for unknown pkt fate command\n");
10347e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            return NL_SKIP;
10357e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        }
10367e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma
10377e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        if (vendor_data == NULL || len == 0) {
10387e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            ALOGE("no vendor data in GetPktFateCommand response; ignoring it\n");
10397e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            return NL_SKIP;
10407e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        }
10417e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma
10427e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
10437e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            if (it.get_type() == LOGGER_ATTRIBUTE_PKT_FATE_NUM) {
10447e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma                *mNoProvidedFates = it.get_u32();
10457e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma                ALOGI("No: of pkt fates provided is %d\n", *mNoProvidedFates);
10467e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            } else {
10477e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma                ALOGE("Ignoring invalid attribute type = %d, size = %d\n",
10487e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma                        it.get_type(), it.get_len());
10497e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma            }
10507e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        }
10517e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma
10527e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        return NL_OK;
10537e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    }
10547e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma
10557e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    int handleEvent(WifiEvent& event) {
10567e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        /* NO events to handle here! */
10577e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        return NL_SKIP;
10587e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    }
10597e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma};
10607e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma
10617e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharmawifi_error wifi_start_pkt_fate_monitoring(wifi_interface_handle handle)
10627e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma{
10637e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    PacketFateCommand *cmd = new PacketFateCommand(handle);
10646af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
10656af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    wifi_error result = (wifi_error)cmd->start();
10666af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    cmd->releaseRef();
10676af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    return result;
10687e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma}
10697e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma
10707e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharmawifi_error wifi_get_tx_pkt_fates(wifi_interface_handle handle,
10717e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        wifi_tx_report *tx_report_bufs, size_t n_requested_fates,
10727e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        size_t *n_provided_fates)
10737e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma{
10747e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    PacketFateCommand *cmd = new PacketFateCommand(handle, tx_report_bufs,
10756af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma                n_requested_fates, n_provided_fates);
10766af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
10776af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    wifi_error result = (wifi_error)cmd->start();
10786af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    cmd->releaseRef();
10796af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    return result;
10807e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma}
10817e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma
10827e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharmawifi_error wifi_get_rx_pkt_fates(wifi_interface_handle handle,
10837e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        wifi_rx_report *rx_report_bufs, size_t n_requested_fates,
10847e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma        size_t *n_provided_fates)
10857e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma{
10867e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    PacketFateCommand *cmd = new PacketFateCommand(handle, rx_report_bufs,
10876af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma                n_requested_fates, n_provided_fates);
10886af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
10896af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    wifi_error result = (wifi_error)cmd->start();
10906af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    cmd->releaseRef();
10916af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    return result;
10927e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma}
1093