| 1 | #include <stdint.h>\r |
| 2 | #include <fcntl.h>\r |
| 3 | #include <sys/socket.h>\r |
| 4 | #include <netlink/genl/genl.h>\r |
| 5 | #include <netlink/genl/family.h>\r |
| 6 | #include <netlink/genl/ctrl.h>\r |
| 7 | #include <linux/rtnetlink.h>\r |
| 8 | #include <netpacket/packet.h>\r |
| 9 | #include <linux/filter.h>\r |
| 10 | #include <linux/errqueue.h>\r |
| 11 | \r |
| 12 | #include <linux/pkt_sched.h>\r |
| 13 | #include <netlink/object-api.h>\r |
| 14 | #include <netlink/netlink.h>\r |
| 15 | #include <netlink/socket.h>\r |
| 16 | #include <netlink-private/object-api.h>\r |
| 17 | #include <netlink-private/types.h>\r |
| 18 | \r |
| 19 | #include "nl80211_copy.h"\r |
| 20 | #include "sync.h"\r |
| 21 | \r |
| 22 | #define LOG_TAG "WifiHAL"\r |
| 23 | \r |
| 24 | #include <utils/Log.h>\r |
| 25 | \r |
| 26 | #include "wifi_hal.h"\r |
| 27 | #include "common.h"\r |
| 28 | #include "cpp_bindings.h"\r |
| 29 | \r |
| 30 | /* using namespace android; */\r |
| 31 | \r |
| 32 | typedef enum {\r |
| 33 | ENHANCE_LOGGER_START_LOGGING = ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START,\r |
| 34 | ENHANCE_LOGGER_TRIGGER_FW_MEM_DUMP,\r |
| 35 | ENHANCE_LOGGER_GET_FW_MEM_DUMP,\r |
| 36 | ENHANCE_LOGGER_GET_VER,\r |
| 37 | ENHANCE_LOGGER_GET_RING_STATUS,\r |
| 38 | ENHANCE_LOGGER_GET_RING_DATA,\r |
| 39 | ENHANCE_LOGGER_GET_FEATURE,\r |
| 40 | ENHANCE_LOGGER_RESET_LOGGING,\r |
| 41 | ENHANCE_LOGGER_TRIGGER_DRIVER_MEM_DUMP,\r |
| 42 | ENHANCE_LOGGER_GET_DRIVER_MEM_DUMP,\r |
| 43 | ENHANCE_LOGGER_START_PKT_FATE_MONITORING,\r |
| 44 | ENHANCE_LOGGER_GET_TX_PKT_FATES,\r |
| 45 | ENHANCE_LOGGER_GET_RX_PKT_FATES,\r |
| 46 | ENHANCE_LOGGER_GET_WAKE_REASON_STATS,\r |
| 47 | } DEBUG_SUB_COMMAND;\r |
| 48 | \r |
| 49 | typedef enum {\r |
| 50 | ENHANCE_LOGGER_ATTRIBUTE_DRIVER_VER,\r |
| 51 | ENHANCE_LOGGER_ATTRIBUTE_FW_VER,\r |
| 52 | ENHANCE_LOGGER_ATTRIBUTE_RING_ID,\r |
| 53 | ENHANCE_LOGGER_ATTRIBUTE_RING_NAME,\r |
| 54 | ENHANCE_LOGGER_ATTRIBUTE_RING_FLAGS,\r |
| 55 | ENHANCE_LOGGER_ATTRIBUTE_LOG_LEVEL,\r |
| 56 | ENHANCE_LOGGER_ATTRIBUTE_LOG_TIME_INTVAL,\r |
| 57 | ENHANCE_LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE,\r |
| 58 | ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_LEN,\r |
| 59 | ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_DATA,\r |
| 60 | // LOGGER_ATTRIBUTE_FW_ERR_CODE,\r |
| 61 | ENHANCE_LOGGER_ATTRIBUTE_RING_DATA,\r |
| 62 | ENHANCE_LOGGER_ATTRIBUTE_RING_STATUS,\r |
| 63 | ENHANCE_LOGGER_ATTRIBUTE_RING_NUM,\r |
| 64 | ENHANCE_LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN,\r |
| 65 | ENHANCE_LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA,\r |
| 66 | ENHANCE_LOGGER_ATTRIBUTE_PKT_FATE_NUM,\r |
| 67 | ENHANCE_LOGGER_ATTRIBUTE_PKT_FATE_DATA,\r |
| 68 | //Attributes for data used by wake stats subcmd.\r |
| 69 | ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_INVALID = 0,\r |
| 70 | ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_TOTAL_CMD_EVENT_WAKE,\r |
| 71 | ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_CMD_EVENT_WAKE_CNT_PTR,\r |
| 72 | ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_CMD_EVENT_WAKE_CNT_SZ,\r |
| 73 | ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_TOTAL_DRIVER_FW_LOCAL_WAKE,\r |
| 74 | ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_PTR,\r |
| 75 | ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_SZ,\r |
| 76 | ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_TOTAL_RX_DATA_WAKE,\r |
| 77 | ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_RX_UNICAST_CNT,\r |
| 78 | ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_RX_MULTICAST_CNT,\r |
| 79 | ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_RX_BROADCAST_CNT,\r |
| 80 | ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP_PKT,\r |
| 81 | ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_PKT,\r |
| 82 | ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_RA,\r |
| 83 | ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_NA,\r |
| 84 | ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_NS,\r |
| 85 | ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP4_RX_MULTICAST_CNT,\r |
| 86 | ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_RX_MULTICAST_CNT,\r |
| 87 | ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_OTHER_RX_MULTICAST_CNT,\r |
| 88 | } ENHANCE_LOGGER_ATTRIBUTE;\r |
| 89 | \r |
| 90 | typedef enum {\r |
| 91 | DEBUG_OFF = 0,\r |
| 92 | DEBUG_NORMAL,\r |
| 93 | DEBUG_VERBOSE,\r |
| 94 | DEBUG_VERY,\r |
| 95 | DEBUG_VERY_VERY,\r |
| 96 | } ENHANCE_LOGGER_LEVEL;\r |
| 97 | \r |
| 98 | typedef enum {\r |
| 99 | GET_FW_VER,\r |
| 100 | GET_DRV_VER,\r |
| 101 | GET_RING_DATA,\r |
| 102 | GET_RING_STATUS,\r |
| 103 | GET_FEATURE,\r |
| 104 | START_RING_LOG,\r |
| 105 | GET_FW_DUMP,\r |
| 106 | GET_DRIVER_DUMP,\r |
| 107 | } GetCmdType;\r |
| 108 | \r |
| 109 | typedef enum {\r |
| 110 | PACKET_MONITOR_START,\r |
| 111 | TX_PACKET_FATE,\r |
| 112 | RX_PACKET_FATE,\r |
| 113 | } PktFateReqType;\r |
| 114 | \r |
| 115 | class DebugCommand : public WifiCommand\r |
| 116 | {\r |
| 117 | char *mBuff = NULL;\r |
| 118 | int *mBuffSize = NULL;\r |
| 119 | u32 *mNumRings = NULL;\r |
| 120 | wifi_ring_buffer_status *mStatus = NULL;\r |
| 121 | unsigned int *mSupport = NULL;\r |
| 122 | u32 mVerboseLevel = 0;\r |
| 123 | u32 mFlags = 0;\r |
| 124 | u32 mMaxIntervalSec = 0;\r |
| 125 | u32 mMinDataSize = 0;\r |
| 126 | char *mRingName = NULL;\r |
| 127 | GetCmdType mType;\r |
| 128 | \r |
| 129 | public:\r |
| 130 | \r |
| 131 | // constructor for get version\r |
| 132 | DebugCommand(wifi_interface_handle iface, char *buffer, int *buffer_size,\r |
| 133 | GetCmdType cmdType)\r |
| 134 | : WifiCommand(iface, 0), mBuff(buffer), mBuffSize(buffer_size), mType\r |
| 135 | (cmdType)\r |
| 136 | {\r |
| 137 | memset(mBuff, 0, *mBuffSize);\r |
| 138 | }\r |
| 139 | \r |
| 140 | // constructor for ring data\r |
| 141 | DebugCommand(wifi_interface_handle iface, char *ring_name, GetCmdType cmdType)\r |
| 142 | : WifiCommand(iface, 0), mRingName(ring_name), mType(cmdType)\r |
| 143 | { }\r |
| 144 | \r |
| 145 | // constructor for ring status\r |
| 146 | DebugCommand(wifi_interface_handle iface, u32 *num_rings,\r |
| 147 | wifi_ring_buffer_status *status, GetCmdType cmdType)\r |
| 148 | : WifiCommand(iface, 0), mNumRings(num_rings), mStatus(status), mType(cmdType)\r |
| 149 | {\r |
| 150 | memset(mStatus, 0, sizeof(wifi_ring_buffer_status) * (*mNumRings));\r |
| 151 | }\r |
| 152 | \r |
| 153 | // constructor for feature set\r |
| 154 | DebugCommand(wifi_interface_handle iface, unsigned int *support, GetCmdType cmdType)\r |
| 155 | : WifiCommand(iface, 0), mSupport(support), mType(cmdType)\r |
| 156 | { }\r |
| 157 | \r |
| 158 | // constructor for ring params\r |
| 159 | DebugCommand(wifi_interface_handle iface, u32 verbose_level, u32 flags,\r |
| 160 | u32 max_interval_sec, u32 min_data_size, char *ring_name, GetCmdType cmdType)\r |
| 161 | : WifiCommand(iface, 0), mVerboseLevel(verbose_level), mFlags(flags),\r |
| 162 | mMaxIntervalSec(max_interval_sec), mMinDataSize(min_data_size),\r |
| 163 | mRingName(ring_name), mType(cmdType)\r |
| 164 | { }\r |
| 165 | \r |
| 166 | int createRingRequest(WifiRequest& request) {\r |
| 167 | int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_START_LOGGING);\r |
| 168 | if (result != WIFI_SUCCESS) {\r |
| 169 | ALOGE("Failed to create start ring logger request; result = %d", result);\r |
| 170 | return result;\r |
| 171 | }\r |
| 172 | \r |
| 173 | nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);\r |
| 174 | \r |
| 175 | result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_LOG_LEVEL, mVerboseLevel);\r |
| 176 | if (result != WIFI_SUCCESS) {\r |
| 177 | ALOGE("Failed to put log level; result = %d", result);\r |
| 178 | return result;\r |
| 179 | }\r |
| 180 | result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_RING_FLAGS, mFlags);\r |
| 181 | if (result != WIFI_SUCCESS) {\r |
| 182 | ALOGE("Failed to put ring flags; result = %d", result);\r |
| 183 | return result;\r |
| 184 | }\r |
| 185 | result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_LOG_TIME_INTVAL, mMaxIntervalSec);\r |
| 186 | if (result != WIFI_SUCCESS) {\r |
| 187 | ALOGE("Failed to put log time interval; result = %d", result);\r |
| 188 | return result;\r |
| 189 | }\r |
| 190 | result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE, mMinDataSize);\r |
| 191 | if (result != WIFI_SUCCESS) {\r |
| 192 | ALOGE("Failed to put min data size; result = %d", result);\r |
| 193 | return result;\r |
| 194 | }\r |
| 195 | result = request.put_string(ENHANCE_LOGGER_ATTRIBUTE_RING_NAME, mRingName);\r |
| 196 | if (result != WIFI_SUCCESS) {\r |
| 197 | ALOGE("Failed to put ringbuffer name; result = %d", result);\r |
| 198 | return result;\r |
| 199 | }\r |
| 200 | request.attr_end(data);\r |
| 201 | \r |
| 202 | return WIFI_SUCCESS;\r |
| 203 | }\r |
| 204 | \r |
| 205 | int createRequest(WifiRequest &request) {\r |
| 206 | int result;\r |
| 207 | \r |
| 208 | switch (mType) {\r |
| 209 | case GET_FW_VER:\r |
| 210 | {\r |
| 211 | result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_VER);\r |
| 212 | if (result != WIFI_SUCCESS) {\r |
| 213 | ALOGE("Failed to create get fw version request; result = %d", result);\r |
| 214 | return result;\r |
| 215 | }\r |
| 216 | \r |
| 217 | nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);\r |
| 218 | \r |
| 219 | // Driver expecting only attribute type, passing mbuff as data with\r |
| 220 | // length 0 to avoid undefined state\r |
| 221 | result = request.put(ENHANCE_LOGGER_ATTRIBUTE_FW_VER, mBuff, 0);\r |
| 222 | if (result != WIFI_SUCCESS) {\r |
| 223 | ALOGE("Failed to put get fw version request; result = %d", result);\r |
| 224 | return result;\r |
| 225 | }\r |
| 226 | request.attr_end(data);\r |
| 227 | break;\r |
| 228 | }\r |
| 229 | \r |
| 230 | case GET_DRV_VER:\r |
| 231 | {\r |
| 232 | result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_VER);\r |
| 233 | if (result != WIFI_SUCCESS) {\r |
| 234 | ALOGE("Failed to create get drv version request; result = %d", result);\r |
| 235 | return result;\r |
| 236 | }\r |
| 237 | \r |
| 238 | nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);\r |
| 239 | \r |
| 240 | // Driver expecting only attribute type, passing mbuff as data with\r |
| 241 | // length 0 to avoid undefined state\r |
| 242 | result = request.put(ENHANCE_LOGGER_ATTRIBUTE_DRIVER_VER, mBuff, 0);\r |
| 243 | \r |
| 244 | if (result != WIFI_SUCCESS) {\r |
| 245 | ALOGE("Failed to put get drv version request; result = %d", result);\r |
| 246 | return result;\r |
| 247 | }\r |
| 248 | request.attr_end(data);\r |
| 249 | break;\r |
| 250 | }\r |
| 251 | \r |
| 252 | case GET_RING_DATA:\r |
| 253 | {\r |
| 254 | result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_RING_DATA);\r |
| 255 | if (result != WIFI_SUCCESS) {\r |
| 256 | ALOGE("Failed to create get ring data request; result = %d", result);\r |
| 257 | return result;\r |
| 258 | }\r |
| 259 | \r |
| 260 | nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);\r |
| 261 | result = request.put_string(ENHANCE_LOGGER_ATTRIBUTE_RING_NAME, mRingName);\r |
| 262 | if (result != WIFI_SUCCESS) {\r |
| 263 | ALOGE("Failed to put ring data request; result = %d", result);\r |
| 264 | return result;\r |
| 265 | }\r |
| 266 | request.attr_end(data);\r |
| 267 | break;\r |
| 268 | }\r |
| 269 | \r |
| 270 | case GET_RING_STATUS:\r |
| 271 | {\r |
| 272 | result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_RING_STATUS);\r |
| 273 | if (result != WIFI_SUCCESS) {\r |
| 274 | ALOGE("Failed to create get ring status request; result = %d", result);\r |
| 275 | return result;\r |
| 276 | }\r |
| 277 | break;\r |
| 278 | }\r |
| 279 | \r |
| 280 | case GET_FEATURE:\r |
| 281 | {\r |
| 282 | result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_FEATURE);\r |
| 283 | if (result != WIFI_SUCCESS) {\r |
| 284 | ALOGE("Failed to create get feature request; result = %d", result);\r |
| 285 | return result;\r |
| 286 | }\r |
| 287 | break;\r |
| 288 | }\r |
| 289 | \r |
| 290 | case START_RING_LOG:\r |
| 291 | result = createRingRequest(request);\r |
| 292 | break;\r |
| 293 | \r |
| 294 | default:\r |
| 295 | ALOGE("Unknown Debug command");\r |
| 296 | result = WIFI_ERROR_UNKNOWN;\r |
| 297 | }\r |
| 298 | return result;\r |
| 299 | }\r |
| 300 | \r |
| 301 | int start() {\r |
| 302 | // ALOGD("Start debug command");\r |
| 303 | WifiRequest request(familyId(), ifaceId());\r |
| 304 | int result = createRequest(request);\r |
| 305 | if (result != WIFI_SUCCESS) {\r |
| 306 | ALOGE("Failed to create debug request; result = %d", result);\r |
| 307 | return result;\r |
| 308 | }\r |
| 309 | \r |
| 310 | result = requestResponse(request);\r |
| 311 | if (result != WIFI_SUCCESS) {\r |
| 312 | ALOGE("Failed to register debug response; result = %d", result);\r |
| 313 | }\r |
| 314 | return result;\r |
| 315 | }\r |
| 316 | \r |
| 317 | virtual int handleResponse(WifiEvent& reply) {\r |
| 318 | ALOGD("In DebugCommand::handleResponse");\r |
| 319 | \r |
| 320 | if (reply.get_cmd() != NL80211_CMD_VENDOR) {\r |
| 321 | ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());\r |
| 322 | return NL_SKIP;\r |
| 323 | }\r |
| 324 | \r |
| 325 | switch (mType) {\r |
| 326 | case GET_DRV_VER:\r |
| 327 | case GET_FW_VER:\r |
| 328 | {\r |
| 329 | void *data = reply.get_vendor_data();\r |
| 330 | int len = reply.get_vendor_data_len();\r |
| 331 | \r |
| 332 | ALOGD("len = %d, expected len = %d", len, *mBuffSize);\r |
| 333 | memcpy(mBuff, data, min(len, *mBuffSize));\r |
| 334 | if (*mBuffSize < len)\r |
| 335 | return NL_SKIP;\r |
| 336 | *mBuffSize = len;\r |
| 337 | break;\r |
| 338 | }\r |
| 339 | \r |
| 340 | case START_RING_LOG:\r |
| 341 | case GET_RING_DATA:\r |
| 342 | break;\r |
| 343 | \r |
| 344 | case GET_RING_STATUS:\r |
| 345 | {\r |
| 346 | nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);\r |
| 347 | int len = reply.get_vendor_data_len();\r |
| 348 | wifi_ring_buffer_status *status(mStatus);\r |
| 349 | \r |
| 350 | if (vendor_data == NULL || len == 0) {\r |
| 351 | ALOGE("No Debug data found");\r |
| 352 | return NL_SKIP;\r |
| 353 | }\r |
| 354 | \r |
| 355 | nl_iterator it(vendor_data);\r |
| 356 | if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_RING_NUM) {\r |
| 357 | unsigned int num_rings = it.get_u32();\r |
| 358 | if (*mNumRings < num_rings) {\r |
| 359 | ALOGE("Not enough status buffers provided, available: %d required: %d",\r |
| 360 | *mNumRings, num_rings);\r |
| 361 | } else {\r |
| 362 | *mNumRings = num_rings;\r |
| 363 | }\r |
| 364 | } else {\r |
| 365 | ALOGE("Unknown attribute: %d expecting %d",\r |
| 366 | it.get_type(), ENHANCE_LOGGER_ATTRIBUTE_RING_NUM);\r |
| 367 | return NL_SKIP;\r |
| 368 | }\r |
| 369 | \r |
| 370 | it.next();\r |
| 371 | if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_RING_STATUS) {\r |
| 372 | memcpy(status, it.get_data(), sizeof(wifi_ring_buffer_status) * (*mNumRings));\r |
| 373 | } else {\r |
| 374 | ALOGW("Ignoring invalid attribute type = %d, size = %d",\r |
| 375 | it.get_type(), it.get_len());\r |
| 376 | }\r |
| 377 | break;\r |
| 378 | }\r |
| 379 | \r |
| 380 | case GET_FEATURE:\r |
| 381 | {\r |
| 382 | void *data = reply.get_vendor_data();\r |
| 383 | \r |
| 384 | ALOGD("len = %d, expected len = %lu", reply.get_vendor_data_len(), (unsigned long)sizeof(unsigned int));\r |
| 385 | memcpy(mSupport, data, sizeof(unsigned int));\r |
| 386 | break;\r |
| 387 | }\r |
| 388 | \r |
| 389 | default:\r |
| 390 | ALOGW("Unknown Debug command");\r |
| 391 | }\r |
| 392 | return NL_OK;\r |
| 393 | }\r |
| 394 | \r |
| 395 | virtual int handleEvent(WifiEvent& event) {\r |
| 396 | /* NO events! */\r |
| 397 | return NL_SKIP;\r |
| 398 | }\r |
| 399 | };\r |
| 400 | \r |
| 401 | /* API to get supportable feature */\r |
| 402 | wifi_error wifi_get_logger_supported_feature_set(wifi_interface_handle iface,\r |
| 403 | unsigned int *support)\r |
| 404 | {\r |
| 405 | if (support) {\r |
| 406 | DebugCommand *cmd = new DebugCommand(iface, support, GET_FEATURE);\r |
| 407 | NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r |
| 408 | wifi_error result = (wifi_error)cmd->start();\r |
| 409 | cmd->releaseRef();\r |
| 410 | return result;\r |
| 411 | } else {\r |
| 412 | ALOGE("Get support buffer NULL");\r |
| 413 | return WIFI_ERROR_INVALID_ARGS;\r |
| 414 | }\r |
| 415 | }\r |
| 416 | \r |
| 417 | /* API to get the status of all ring buffers supported by driver */\r |
| 418 | wifi_error wifi_get_ring_buffers_status(wifi_interface_handle iface,\r |
| 419 | u32 *num_rings, wifi_ring_buffer_status *status)\r |
| 420 | {\r |
| 421 | if (status && num_rings) {\r |
| 422 | DebugCommand *cmd = new DebugCommand(iface, num_rings, status, GET_RING_STATUS);\r |
| 423 | NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r |
| 424 | wifi_error result = (wifi_error)cmd->start();\r |
| 425 | cmd->releaseRef();\r |
| 426 | return result;\r |
| 427 | } else {\r |
| 428 | ALOGE("Ring status buffer NULL");\r |
| 429 | return WIFI_ERROR_INVALID_ARGS;\r |
| 430 | }\r |
| 431 | }\r |
| 432 | \r |
| 433 | /* API to collect driver records */\r |
| 434 | wifi_error wifi_get_ring_data(wifi_interface_handle iface, char *ring_name)\r |
| 435 | {\r |
| 436 | DebugCommand *cmd = new DebugCommand(iface, ring_name, GET_RING_DATA);\r |
| 437 | NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r |
| 438 | wifi_error result = (wifi_error)cmd->start();\r |
| 439 | cmd->releaseRef();\r |
| 440 | return result;\r |
| 441 | }\r |
| 442 | \r |
| 443 | wifi_error wifi_start_logging(wifi_interface_handle iface, u32 verbose_level,\r |
| 444 | u32 flags, u32 max_interval_sec, u32 min_data_size, char *ring_name)\r |
| 445 | {\r |
| 446 | if (ring_name) {\r |
| 447 | DebugCommand *cmd = new DebugCommand(iface, verbose_level, flags, max_interval_sec,\r |
| 448 | min_data_size, ring_name, START_RING_LOG);\r |
| 449 | NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r |
| 450 | wifi_error result = (wifi_error)cmd->start();\r |
| 451 | cmd->releaseRef();\r |
| 452 | return result;\r |
| 453 | } else {\r |
| 454 | ALOGE("Ring name NULL");\r |
| 455 | return WIFI_ERROR_INVALID_ARGS;\r |
| 456 | }\r |
| 457 | }\r |
| 458 | \r |
| 459 | /* API to collect a firmware version string */\r |
| 460 | wifi_error wifi_get_firmware_version(wifi_interface_handle iface, char *buffer,\r |
| 461 | int buffer_size)\r |
| 462 | {\r |
| 463 | if (buffer && (buffer_size > 0)) {\r |
| 464 | DebugCommand *cmd = new DebugCommand(iface, buffer, &buffer_size, GET_FW_VER);\r |
| 465 | NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r |
| 466 | wifi_error result = (wifi_error)cmd->start();\r |
| 467 | cmd->releaseRef();\r |
| 468 | return result;\r |
| 469 | } else {\r |
| 470 | ALOGE("FW version buffer NULL");\r |
| 471 | return WIFI_ERROR_INVALID_ARGS;\r |
| 472 | }\r |
| 473 | }\r |
| 474 | \r |
| 475 | /* API to collect a driver version string */\r |
| 476 | wifi_error wifi_get_driver_version(wifi_interface_handle iface, char *buffer, int buffer_size)\r |
| 477 | {\r |
| 478 | if (buffer && (buffer_size > 0)) {\r |
| 479 | DebugCommand *cmd = new DebugCommand(iface, buffer, &buffer_size, GET_DRV_VER);\r |
| 480 | NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r |
| 481 | wifi_error result = (wifi_error)cmd->start();\r |
| 482 | cmd->releaseRef();\r |
| 483 | return result;\r |
| 484 | } else {\r |
| 485 | ALOGE("Driver version buffer NULL");\r |
| 486 | return WIFI_ERROR_INVALID_ARGS;\r |
| 487 | }\r |
| 488 | }\r |
| 489 | \r |
| 490 | \r |
| 491 | ///////////////////////////////////////////////////////////////////////////////\r |
| 492 | class SetLogHandler : public WifiCommand\r |
| 493 | {\r |
| 494 | wifi_ring_buffer_data_handler mHandler;\r |
| 495 | \r |
| 496 | public:\r |
| 497 | SetLogHandler(wifi_interface_handle iface, int id, wifi_ring_buffer_data_handler handler)\r |
| 498 | : WifiCommand(iface, id), mHandler(handler)\r |
| 499 | { }\r |
| 500 | \r |
| 501 | int start() {\r |
| 502 | ALOGV("Register loghandler");\r |
| 503 | registerVendorHandler(GOOGLE_OUI, ENHANCE_LOGGER_RING_EVENT);\r |
| 504 | return WIFI_SUCCESS;\r |
| 505 | }\r |
| 506 | \r |
| 507 | virtual int cancel() {\r |
| 508 | /* Send a command to driver to stop generating logging events */\r |
| 509 | ALOGV("Clear loghandler");\r |
| 510 | \r |
| 511 | /* unregister event handler */\r |
| 512 | unregisterVendorHandler(GOOGLE_OUI, ENHANCE_LOGGER_RING_EVENT);\r |
| 513 | \r |
| 514 | WifiRequest request(familyId(), ifaceId());\r |
| 515 | int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_RESET_LOGGING);\r |
| 516 | if (result != WIFI_SUCCESS) {\r |
| 517 | ALOGE("failed to create reset request; result = %d", result);\r |
| 518 | return result;\r |
| 519 | }\r |
| 520 | \r |
| 521 | result = requestResponse(request);\r |
| 522 | if (result != WIFI_SUCCESS) {\r |
| 523 | ALOGE("failed to request reset; result = %d", result);\r |
| 524 | return result;\r |
| 525 | }\r |
| 526 | \r |
| 527 | ALOGD("Success to clear loghandler");\r |
| 528 | return WIFI_SUCCESS;\r |
| 529 | }\r |
| 530 | \r |
| 531 | virtual int handleEvent(WifiEvent& event) {\r |
| 532 | char *buffer = NULL;\r |
| 533 | int buffer_size = 0;\r |
| 534 | \r |
| 535 | // ALOGD("In SetLogHandler::handleEvent");\r |
| 536 | nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);\r |
| 537 | int len = event.get_vendor_data_len();\r |
| 538 | int event_id = event.get_vendor_subcmd();\r |
| 539 | // ALOGI("Got Logger event: %d", event_id);\r |
| 540 | \r |
| 541 | if (vendor_data == NULL || len == 0) {\r |
| 542 | ALOGE("No Debug data found");\r |
| 543 | return NL_SKIP;\r |
| 544 | }\r |
| 545 | \r |
| 546 | if(event_id == ENHANCE_LOGGER_RING_EVENT) {\r |
| 547 | wifi_ring_buffer_status status;\r |
| 548 | memset(&status, 0, sizeof(status));\r |
| 549 | \r |
| 550 | for (nl_iterator it(vendor_data); it.has_next(); it.next()) {\r |
| 551 | if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_RING_STATUS) {\r |
| 552 | memcpy(&status, it.get_data(), sizeof(status));\r |
| 553 | } else if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_RING_DATA) {\r |
| 554 | buffer_size = it.get_len();\r |
| 555 | buffer = (char *)it.get_data();\r |
| 556 | } else {\r |
| 557 | ALOGW("Ignoring invalid attribute type = %d, size = %d",\r |
| 558 | it.get_type(), it.get_len());\r |
| 559 | }\r |
| 560 | }\r |
| 561 | \r |
| 562 | // ALOGI("Retrieved Debug data");\r |
| 563 | if (mHandler.on_ring_buffer_data) {\r |
| 564 | (*mHandler.on_ring_buffer_data)((char *)status.name, buffer, buffer_size,\r |
| 565 | &status);\r |
| 566 | }\r |
| 567 | } else {\r |
| 568 | ALOGE("Unknown Event");\r |
| 569 | return NL_SKIP;\r |
| 570 | }\r |
| 571 | return NL_OK;\r |
| 572 | }\r |
| 573 | };\r |
| 574 | \r |
| 575 | wifi_error wifi_set_log_handler(wifi_request_id id, wifi_interface_handle iface,\r |
| 576 | wifi_ring_buffer_data_handler handler)\r |
| 577 | {\r |
| 578 | wifi_handle handle = getWifiHandle(iface);\r |
| 579 | ALOGV("Loghandler start, handle = %p", handle);\r |
| 580 | \r |
| 581 | SetLogHandler *cmd = new SetLogHandler(iface, id, handler);\r |
| 582 | NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r |
| 583 | wifi_error result = wifi_register_cmd(handle, id, cmd);\r |
| 584 | if (result != WIFI_SUCCESS) {\r |
| 585 | cmd->releaseRef();\r |
| 586 | return result;\r |
| 587 | }\r |
| 588 | result = (wifi_error)cmd->start();\r |
| 589 | if (result != WIFI_SUCCESS) {\r |
| 590 | wifi_unregister_cmd(handle, id);\r |
| 591 | cmd->releaseRef();\r |
| 592 | return result;\r |
| 593 | }\r |
| 594 | return result;\r |
| 595 | }\r |
| 596 | \r |
| 597 | wifi_error wifi_reset_log_handler(wifi_request_id id, wifi_interface_handle iface)\r |
| 598 | {\r |
| 599 | wifi_handle handle = getWifiHandle(iface);\r |
| 600 | ALOGV("Loghandler reset, wifi_request_id = %d, handle = %p", id, handle);\r |
| 601 | \r |
| 602 | if (id == -1) {\r |
| 603 | wifi_ring_buffer_data_handler handler;\r |
| 604 | memset(&handler, 0, sizeof(handler));\r |
| 605 | \r |
| 606 | SetLogHandler *cmd = new SetLogHandler(iface, id, handler);\r |
| 607 | NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r |
| 608 | cmd->cancel();\r |
| 609 | cmd->releaseRef();\r |
| 610 | return WIFI_SUCCESS;\r |
| 611 | }\r |
| 612 | \r |
| 613 | return wifi_cancel_cmd(id, iface);\r |
| 614 | }\r |
| 615 | \r |
| 616 | ///////////////////////////////////////////////////////////////////////////////\r |
| 617 | class SetAlertHandler : public WifiCommand\r |
| 618 | {\r |
| 619 | wifi_alert_handler mHandler;\r |
| 620 | int mBuffSize;\r |
| 621 | char *mBuff;\r |
| 622 | int mErrCode;\r |
| 623 | \r |
| 624 | public:\r |
| 625 | SetAlertHandler(wifi_interface_handle iface, int id, wifi_alert_handler handler)\r |
| 626 | : WifiCommand(iface, id), mHandler(handler), mBuffSize(0), mBuff(NULL),\r |
| 627 | mErrCode(0)\r |
| 628 | { }\r |
| 629 | \r |
| 630 | int start() {\r |
| 631 | ALOGV("Start Alerting");\r |
| 632 | registerVendorHandler(GOOGLE_OUI, ENHANCE_LOGGER_MEM_DUMP_EVENT);\r |
| 633 | return WIFI_SUCCESS;\r |
| 634 | }\r |
| 635 | \r |
| 636 | virtual int cancel() {\r |
| 637 | ALOGV("Clear alerthandler");\r |
| 638 | \r |
| 639 | /* unregister alert handler */\r |
| 640 | unregisterVendorHandler(GOOGLE_OUI, ENHANCE_LOGGER_MEM_DUMP_EVENT);\r |
| 641 | wifi_unregister_cmd(wifiHandle(), id());\r |
| 642 | ALOGD("Success to clear alerthandler");\r |
| 643 | return WIFI_SUCCESS;\r |
| 644 | }\r |
| 645 | \r |
| 646 | virtual int handleResponse(WifiEvent& reply) {\r |
| 647 | ALOGD("In SetAlertHandler::handleResponse");\r |
| 648 | \r |
| 649 | if (reply.get_cmd() != NL80211_CMD_VENDOR) {\r |
| 650 | ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());\r |
| 651 | return NL_SKIP;\r |
| 652 | }\r |
| 653 | \r |
| 654 | nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);\r |
| 655 | int len = reply.get_vendor_data_len();\r |
| 656 | \r |
| 657 | ALOGD("len = %d", len);\r |
| 658 | if (vendor_data == NULL || len == 0) {\r |
| 659 | ALOGE("no vendor data in memory dump response; ignoring it");\r |
| 660 | return NL_SKIP;\r |
| 661 | }\r |
| 662 | \r |
| 663 | for (nl_iterator it(vendor_data); it.has_next(); it.next()) {\r |
| 664 | if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_DATA) {\r |
| 665 | ALOGI("Initiating alert callback");\r |
| 666 | if (mHandler.on_alert) {\r |
| 667 | (*mHandler.on_alert)(id(), mBuff, mBuffSize, mErrCode);\r |
| 668 | }\r |
| 669 | if (mBuff) {\r |
| 670 | free(mBuff);\r |
| 671 | mBuff = NULL;\r |
| 672 | }\r |
| 673 | }\r |
| 674 | }\r |
| 675 | return NL_OK;\r |
| 676 | }\r |
| 677 | \r |
| 678 | virtual int handleEvent(WifiEvent& event) {\r |
| 679 | char *buffer = NULL;\r |
| 680 | int buffer_size = 0;\r |
| 681 | \r |
| 682 | \r |
| 683 | nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);\r |
| 684 | int len = event.get_vendor_data_len();\r |
| 685 | int event_id = event.get_vendor_subcmd();\r |
| 686 | ALOGI("Got event: %d", event_id);\r |
| 687 | \r |
| 688 | if (vendor_data == NULL || len == 0) {\r |
| 689 | ALOGE("No Debug data found");\r |
| 690 | return NL_SKIP;\r |
| 691 | }\r |
| 692 | \r |
| 693 | if (event_id == ENHANCE_LOGGER_MEM_DUMP_EVENT) {\r |
| 694 | for (nl_iterator it(vendor_data); it.has_next(); it.next()) {\r |
| 695 | if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_LEN) {\r |
| 696 | mBuffSize = it.get_u32();\r |
| 697 | } else if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_RING_DATA) {\r |
| 698 | buffer_size = it.get_len();\r |
| 699 | buffer = (char *)it.get_data();\r |
| 700 | /*\r |
| 701 | } else if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_FW_ERR_CODE) {\r |
| 702 | mErrCode = it.get_u32();\r |
| 703 | */\r |
| 704 | } else {\r |
| 705 | ALOGW("Ignoring invalid attribute type = %d, size = %d",\r |
| 706 | it.get_type(), it.get_len());\r |
| 707 | }\r |
| 708 | }\r |
| 709 | if (mBuffSize) {\r |
| 710 | ALOGD("dump size: %d meta data size: %d", mBuffSize, buffer_size);\r |
| 711 | if (mBuff) free(mBuff);\r |
| 712 | mBuff = (char *)malloc(mBuffSize + buffer_size);\r |
| 713 | if (!mBuff) {\r |
| 714 | ALOGE("Buffer allocation failed");\r |
| 715 | return NL_SKIP;\r |
| 716 | }\r |
| 717 | memcpy(mBuff, buffer, buffer_size);\r |
| 718 | \r |
| 719 | WifiRequest request(familyId(), ifaceId());\r |
| 720 | int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_MEM_DUMP_EVENT);\r |
| 721 | if (result != WIFI_SUCCESS) {\r |
| 722 | ALOGE("Failed to create get memory dump request; result = %d", result);\r |
| 723 | free(mBuff);\r |
| 724 | return NL_SKIP;\r |
| 725 | }\r |
| 726 | nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);\r |
| 727 | result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_LEN, mBuffSize);\r |
| 728 | if (result != WIFI_SUCCESS) {\r |
| 729 | ALOGE("Failed to put get memory dump request; result = %d", result);\r |
| 730 | return result;\r |
| 731 | }\r |
| 732 | \r |
| 733 | result = request.put_u64(ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_DATA,\r |
| 734 | (uint64_t)(mBuff+buffer_size));\r |
| 735 | if (result != WIFI_SUCCESS) {\r |
| 736 | ALOGE("Failed to put get memory dump request; result = %d", result);\r |
| 737 | return result;\r |
| 738 | }\r |
| 739 | \r |
| 740 | request.attr_end(data);\r |
| 741 | mBuffSize += buffer_size;\r |
| 742 | \r |
| 743 | result = requestResponse(request);\r |
| 744 | \r |
| 745 | if (result != WIFI_SUCCESS) {\r |
| 746 | ALOGE("Failed to register get momory dump response; result = %d", result);\r |
| 747 | }\r |
| 748 | } else {\r |
| 749 | ALOGE("dump event missing dump length attribute");\r |
| 750 | return NL_SKIP;\r |
| 751 | }\r |
| 752 | }\r |
| 753 | return NL_OK;\r |
| 754 | }\r |
| 755 | };\r |
| 756 | \r |
| 757 | wifi_error wifi_set_alert_handler(wifi_request_id id, wifi_interface_handle iface,\r |
| 758 | wifi_alert_handler handler)\r |
| 759 | {\r |
| 760 | wifi_handle handle = getWifiHandle(iface);\r |
| 761 | ALOGV("Alerthandler start, handle = %p", handle);\r |
| 762 | \r |
| 763 | SetAlertHandler *cmd = new SetAlertHandler(iface, id, handler);\r |
| 764 | NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r |
| 765 | wifi_error result = wifi_register_cmd(handle, id, cmd);\r |
| 766 | if (result != WIFI_SUCCESS) {\r |
| 767 | cmd->releaseRef();\r |
| 768 | return result;\r |
| 769 | }\r |
| 770 | result = (wifi_error)cmd->start();\r |
| 771 | if (result != WIFI_SUCCESS) {\r |
| 772 | wifi_unregister_cmd(handle, id);\r |
| 773 | cmd->releaseRef();\r |
| 774 | return result;\r |
| 775 | }\r |
| 776 | return result;\r |
| 777 | }\r |
| 778 | \r |
| 779 | wifi_error wifi_reset_alert_handler(wifi_request_id id, wifi_interface_handle iface)\r |
| 780 | {\r |
| 781 | wifi_handle handle = getWifiHandle(iface);\r |
| 782 | ALOGV("Alerthandler reset, wifi_request_id = %d, handle = %p", id, handle);\r |
| 783 | \r |
| 784 | if (id == -1) {\r |
| 785 | wifi_alert_handler handler;\r |
| 786 | memset(&handler, 0, sizeof(handler));\r |
| 787 | \r |
| 788 | SetAlertHandler *cmd = new SetAlertHandler(iface, id, handler);\r |
| 789 | NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r |
| 790 | cmd->cancel();\r |
| 791 | cmd->releaseRef();\r |
| 792 | return WIFI_SUCCESS;\r |
| 793 | }\r |
| 794 | \r |
| 795 | return wifi_cancel_cmd(id, iface);\r |
| 796 | }\r |
| 797 | \r |
| 798 | \r |
| 799 | class PacketFateCommand: public WifiCommand\r |
| 800 | {\r |
| 801 | void *mReportBufs = NULL;\r |
| 802 | size_t mNoReqFates = 0;\r |
| 803 | size_t *mNoProvidedFates = NULL;\r |
| 804 | PktFateReqType mReqType;\r |
| 805 | \r |
| 806 | public:\r |
| 807 | PacketFateCommand(wifi_interface_handle handle)\r |
| 808 | : WifiCommand(handle, 0), mReqType(PACKET_MONITOR_START)\r |
| 809 | { }\r |
| 810 | \r |
| 811 | PacketFateCommand(wifi_interface_handle handle, wifi_tx_report *tx_report_bufs,\r |
| 812 | size_t n_requested_fates, size_t *n_provided_fates)\r |
| 813 | : WifiCommand(handle, 0), mReportBufs(tx_report_bufs),\r |
| 814 | mNoReqFates(n_requested_fates), mNoProvidedFates(n_provided_fates),\r |
| 815 | mReqType(TX_PACKET_FATE)\r |
| 816 | { }\r |
| 817 | \r |
| 818 | PacketFateCommand(wifi_interface_handle handle, wifi_rx_report *rx_report_bufs,\r |
| 819 | size_t n_requested_fates, size_t *n_provided_fates)\r |
| 820 | : WifiCommand(handle, 0), mReportBufs(rx_report_bufs),\r |
| 821 | mNoReqFates(n_requested_fates), mNoProvidedFates(n_provided_fates),\r |
| 822 | mReqType(RX_PACKET_FATE)\r |
| 823 | { }\r |
| 824 | \r |
| 825 | int createRequest(WifiRequest& request) {\r |
| 826 | if (mReqType == TX_PACKET_FATE) {\r |
| 827 | ALOGD("%s Get Tx packet fate request\n", __FUNCTION__);\r |
| 828 | return createTxPktFateRequest(request);\r |
| 829 | } else if (mReqType == RX_PACKET_FATE) {\r |
| 830 | ALOGD("%s Get Rx packet fate request\n", __FUNCTION__);\r |
| 831 | return createRxPktFateRequest(request);\r |
| 832 | } else if (mReqType == PACKET_MONITOR_START) {\r |
| 833 | ALOGD("%s Monitor packet fate request\n", __FUNCTION__);\r |
| 834 | return createMonitorPktFateRequest(request);\r |
| 835 | } else {\r |
| 836 | ALOGE("%s Unknown packet fate request\n", __FUNCTION__);\r |
| 837 | return WIFI_ERROR_NOT_SUPPORTED;\r |
| 838 | }\r |
| 839 | return WIFI_SUCCESS;\r |
| 840 | }\r |
| 841 | \r |
| 842 | int createMonitorPktFateRequest(WifiRequest& request) {\r |
| 843 | int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_START_PKT_FATE_MONITORING);\r |
| 844 | if (result < 0) {\r |
| 845 | return result;\r |
| 846 | }\r |
| 847 | \r |
| 848 | nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);\r |
| 849 | request.attr_end(data);\r |
| 850 | return result;\r |
| 851 | }\r |
| 852 | \r |
| 853 | int createTxPktFateRequest(WifiRequest& request) {\r |
| 854 | int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_TX_PKT_FATES);\r |
| 855 | if (result < 0) {\r |
| 856 | return result;\r |
| 857 | }\r |
| 858 | \r |
| 859 | memset(mReportBufs, 0, (mNoReqFates * sizeof(wifi_tx_report)));\r |
| 860 | nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);\r |
| 861 | result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_PKT_FATE_NUM, mNoReqFates);\r |
| 862 | if (result < 0) {\r |
| 863 | return result;\r |
| 864 | }\r |
| 865 | result = request.put_u64(ENHANCE_LOGGER_ATTRIBUTE_PKT_FATE_DATA, (uint64_t)mReportBufs);\r |
| 866 | if (result < 0) {\r |
| 867 | return result;\r |
| 868 | }\r |
| 869 | request.attr_end(data);\r |
| 870 | return result;\r |
| 871 | }\r |
| 872 | \r |
| 873 | int createRxPktFateRequest(WifiRequest& request) {\r |
| 874 | int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_RX_PKT_FATES);\r |
| 875 | if (result < 0) {\r |
| 876 | return result;\r |
| 877 | }\r |
| 878 | \r |
| 879 | memset(mReportBufs, 0, (mNoReqFates * sizeof(wifi_rx_report)));\r |
| 880 | nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);\r |
| 881 | result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_PKT_FATE_NUM, mNoReqFates);\r |
| 882 | if (result < 0) {\r |
| 883 | return result;\r |
| 884 | }\r |
| 885 | result = request.put_u64(ENHANCE_LOGGER_ATTRIBUTE_PKT_FATE_DATA, (uint64_t)mReportBufs);\r |
| 886 | if (result < 0) {\r |
| 887 | return result;\r |
| 888 | }\r |
| 889 | request.attr_end(data);\r |
| 890 | return result;\r |
| 891 | }\r |
| 892 | \r |
| 893 | int start() {\r |
| 894 | ALOGD("Start get packet fate command\n");\r |
| 895 | WifiRequest request(familyId(), ifaceId());\r |
| 896 | \r |
| 897 | int result = createRequest(request);\r |
| 898 | if (result < 0) {\r |
| 899 | ALOGE("Failed to create get pkt fate request; result = %d\n", result);\r |
| 900 | return result;\r |
| 901 | }\r |
| 902 | \r |
| 903 | result = requestResponse(request);\r |
| 904 | if (result != WIFI_SUCCESS) {\r |
| 905 | ALOGE("Failed to register get pkt fate response; result = %d\n", result);\r |
| 906 | }\r |
| 907 | return result;\r |
| 908 | }\r |
| 909 | \r |
| 910 | int handleResponse(WifiEvent& reply) {\r |
| 911 | ALOGD("In GetPktFateCommand::handleResponse\n");\r |
| 912 | \r |
| 913 | if (reply.get_cmd() != NL80211_CMD_VENDOR) {\r |
| 914 | ALOGI("Ignoring reply with cmd = %d", reply.get_cmd());\r |
| 915 | return NL_SKIP;\r |
| 916 | }\r |
| 917 | \r |
| 918 | int id = reply.get_vendor_id();\r |
| 919 | int subcmd = reply.get_vendor_subcmd();\r |
| 920 | nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);\r |
| 921 | int len = reply.get_vendor_data_len();\r |
| 922 | \r |
| 923 | ALOGI("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);\r |
| 924 | \r |
| 925 | if (mReqType == TX_PACKET_FATE) {\r |
| 926 | ALOGI("Response recieved for get TX pkt fate command\n");\r |
| 927 | } else if (mReqType == RX_PACKET_FATE) {\r |
| 928 | ALOGI("Response recieved for get RX pkt fate command\n");\r |
| 929 | } else if (mReqType == PACKET_MONITOR_START) {\r |
| 930 | ALOGI("Response recieved for monitor pkt fate command\n");\r |
| 931 | return NL_OK;\r |
| 932 | } else {\r |
| 933 | ALOGE("Response recieved for unknown pkt fate command\n");\r |
| 934 | return NL_SKIP;\r |
| 935 | }\r |
| 936 | \r |
| 937 | if (vendor_data == NULL || len == 0) {\r |
| 938 | ALOGE("no vendor data in GetPktFateCommand response; ignoring it\n");\r |
| 939 | return NL_SKIP;\r |
| 940 | }\r |
| 941 | \r |
| 942 | for (nl_iterator it(vendor_data); it.has_next(); it.next()) {\r |
| 943 | if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_PKT_FATE_NUM) {\r |
| 944 | *mNoProvidedFates = it.get_u32();\r |
| 945 | ALOGI("No: of pkt fates provided is %zu\n", *mNoProvidedFates);\r |
| 946 | } else {\r |
| 947 | ALOGE("Ignoring invalid attribute type = %d, size = %d\n",\r |
| 948 | it.get_type(), it.get_len());\r |
| 949 | }\r |
| 950 | }\r |
| 951 | \r |
| 952 | return NL_OK;\r |
| 953 | }\r |
| 954 | \r |
| 955 | int handleEvent(WifiEvent& event) {\r |
| 956 | /* NO events to handle here! */\r |
| 957 | return NL_SKIP;\r |
| 958 | }\r |
| 959 | };\r |
| 960 | \r |
| 961 | wifi_error wifi_start_pkt_fate_monitoring(wifi_interface_handle handle)\r |
| 962 | {\r |
| 963 | PacketFateCommand *cmd = new PacketFateCommand(handle);\r |
| 964 | NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r |
| 965 | wifi_error result = (wifi_error)cmd->start();\r |
| 966 | cmd->releaseRef();\r |
| 967 | return result;\r |
| 968 | }\r |
| 969 | \r |
| 970 | wifi_error wifi_get_tx_pkt_fates(wifi_interface_handle handle,\r |
| 971 | wifi_tx_report *tx_report_bufs, size_t n_requested_fates,\r |
| 972 | size_t *n_provided_fates)\r |
| 973 | {\r |
| 974 | PacketFateCommand *cmd = new PacketFateCommand(handle, tx_report_bufs,\r |
| 975 | n_requested_fates, n_provided_fates);\r |
| 976 | NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r |
| 977 | wifi_error result = (wifi_error)cmd->start();\r |
| 978 | cmd->releaseRef();\r |
| 979 | memset(tx_report_bufs, 0, (n_requested_fates * sizeof(wifi_tx_report)));\r |
| 980 | return result;\r |
| 981 | }\r |
| 982 | \r |
| 983 | wifi_error wifi_get_rx_pkt_fates(wifi_interface_handle handle,\r |
| 984 | wifi_rx_report *rx_report_bufs, size_t n_requested_fates,\r |
| 985 | size_t *n_provided_fates)\r |
| 986 | {\r |
| 987 | PacketFateCommand *cmd = new PacketFateCommand(handle, rx_report_bufs,\r |
| 988 | n_requested_fates, n_provided_fates);\r |
| 989 | NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r |
| 990 | wifi_error result = (wifi_error)cmd->start();\r |
| 991 | cmd->releaseRef();\r |
| 992 | memset(rx_report_bufs, 0, (n_requested_fates * sizeof(wifi_rx_report)));\r |
| 993 | return result;\r |
| 994 | }\r |
| 995 | \r |
| 996 | class MemoryDumpCommand: public WifiCommand\r |
| 997 | {\r |
| 998 | wifi_firmware_memory_dump_handler mHandler;\r |
| 999 | wifi_driver_memory_dump_callbacks mcallback;\r |
| 1000 | int mBuffSize;\r |
| 1001 | char *mBuff;\r |
| 1002 | GetCmdType mType;\r |
| 1003 | \r |
| 1004 | public:\r |
| 1005 | MemoryDumpCommand(wifi_interface_handle iface, wifi_firmware_memory_dump_handler handler, GetCmdType cmdtype )\r |
| 1006 | : WifiCommand(iface, 0), mHandler(handler), mBuffSize(0), mBuff(NULL), mType(cmdtype)\r |
| 1007 | {\r |
| 1008 | memset(&mcallback, 0, sizeof(wifi_driver_memory_dump_callbacks));\r |
| 1009 | }\r |
| 1010 | \r |
| 1011 | MemoryDumpCommand(wifi_interface_handle iface, wifi_driver_memory_dump_callbacks callback, GetCmdType cmdtype)\r |
| 1012 | : WifiCommand(iface, 0), mcallback(callback), mBuffSize(0), mBuff(NULL), mType(cmdtype)\r |
| 1013 | {\r |
| 1014 | memset(&mHandler, 0, sizeof(wifi_firmware_memory_dump_handler));\r |
| 1015 | }\r |
| 1016 | \r |
| 1017 | int createRequest(WifiRequest &request) {\r |
| 1018 | int result;\r |
| 1019 | \r |
| 1020 | switch (mType) {\r |
| 1021 | case GET_FW_DUMP:\r |
| 1022 | {\r |
| 1023 | result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_TRIGGER_FW_MEM_DUMP);\r |
| 1024 | if (result != WIFI_SUCCESS) {\r |
| 1025 | ALOGE("Failed to create trigger fw memory dump request; result = %d", result);\r |
| 1026 | return result;\r |
| 1027 | }\r |
| 1028 | break;\r |
| 1029 | }\r |
| 1030 | case GET_DRIVER_DUMP :\r |
| 1031 | {\r |
| 1032 | result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_TRIGGER_DRIVER_MEM_DUMP);\r |
| 1033 | if (result != WIFI_SUCCESS) {\r |
| 1034 | ALOGE("Failed to create trigger driver memory dump request; result = %d", result);\r |
| 1035 | return result;\r |
| 1036 | }\r |
| 1037 | break;\r |
| 1038 | }\r |
| 1039 | default:\r |
| 1040 | ALOGE("Unknown Debug command");\r |
| 1041 | result = WIFI_ERROR_UNKNOWN;\r |
| 1042 | }\r |
| 1043 | return result;\r |
| 1044 | }\r |
| 1045 | int start() {\r |
| 1046 | ALOGD("Start memory dump command");\r |
| 1047 | WifiRequest request(familyId(), ifaceId());\r |
| 1048 | \r |
| 1049 | int result = createRequest(request);\r |
| 1050 | if (result != WIFI_SUCCESS) {\r |
| 1051 | ALOGE("Failed to create trigger memory dump request; result = %d", result);\r |
| 1052 | return result;\r |
| 1053 | }\r |
| 1054 | \r |
| 1055 | result = requestResponse(request);\r |
| 1056 | if (result != WIFI_SUCCESS) {\r |
| 1057 | ALOGE("Failed to register trigger memory dump response; result = %d", result);\r |
| 1058 | }\r |
| 1059 | return result;\r |
| 1060 | }\r |
| 1061 | \r |
| 1062 | virtual int handleResponse(WifiEvent& reply) {\r |
| 1063 | ALOGD("In MemoryDumpCommand::handleResponse");\r |
| 1064 | \r |
| 1065 | if (reply.get_cmd() != NL80211_CMD_VENDOR) {\r |
| 1066 | ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());\r |
| 1067 | return NL_SKIP;\r |
| 1068 | }\r |
| 1069 | \r |
| 1070 | nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);\r |
| 1071 | int len = reply.get_vendor_data_len();\r |
| 1072 | \r |
| 1073 | ALOGD("len = %d", len);\r |
| 1074 | if (vendor_data == NULL || len == 0) {\r |
| 1075 | ALOGE("no vendor data in memory dump response; ignoring it");\r |
| 1076 | return NL_SKIP;\r |
| 1077 | }\r |
| 1078 | switch(mType) {\r |
| 1079 | case GET_FW_DUMP:\r |
| 1080 | for (nl_iterator it(vendor_data); it.has_next(); it.next()) {\r |
| 1081 | if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_LEN) {\r |
| 1082 | mBuffSize = it.get_u32();\r |
| 1083 | if (mBuff)\r |
| 1084 | free(mBuff);\r |
| 1085 | mBuff = (char *)malloc(mBuffSize);\r |
| 1086 | if (!mBuff) {\r |
| 1087 | ALOGE("Buffer allocation failed");\r |
| 1088 | return NL_SKIP;\r |
| 1089 | }\r |
| 1090 | WifiRequest request(familyId(), ifaceId());\r |
| 1091 | int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_FW_MEM_DUMP);\r |
| 1092 | if (result != WIFI_SUCCESS) {\r |
| 1093 | ALOGE("Failed to create get fw memory dump request; result = %d", result);\r |
| 1094 | free(mBuff);\r |
| 1095 | return NL_SKIP;\r |
| 1096 | }\r |
| 1097 | nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);\r |
| 1098 | result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_LEN, mBuffSize);\r |
| 1099 | if (result != WIFI_SUCCESS) {\r |
| 1100 | ALOGE("Failed to put get fw memory dump request; result = %d", result);\r |
| 1101 | return result;\r |
| 1102 | }\r |
| 1103 | result = request.put_u64(ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_DATA, (uint64_t)mBuff);\r |
| 1104 | if (result != WIFI_SUCCESS) {\r |
| 1105 | ALOGE("Failed to put get fw memory dump request; result = %d", result);\r |
| 1106 | return result;\r |
| 1107 | }\r |
| 1108 | request.attr_end(data);\r |
| 1109 | result = requestResponse(request);\r |
| 1110 | if (result != WIFI_SUCCESS) {\r |
| 1111 | ALOGE("Failed to register get fw momory dump response; result = %d", result);\r |
| 1112 | }\r |
| 1113 | } else if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_DATA) {\r |
| 1114 | ALOGI("Initiating memory dump callback");\r |
| 1115 | if (mHandler.on_firmware_memory_dump) {\r |
| 1116 | (*mHandler.on_firmware_memory_dump)(mBuff, mBuffSize);\r |
| 1117 | }\r |
| 1118 | if (mBuff) {\r |
| 1119 | free(mBuff);\r |
| 1120 | mBuff = NULL;\r |
| 1121 | }\r |
| 1122 | } else {\r |
| 1123 | ALOGW("Ignoring invalid attribute type = %d, size = %d",\r |
| 1124 | it.get_type(), it.get_len());\r |
| 1125 | }\r |
| 1126 | }\r |
| 1127 | break;\r |
| 1128 | case GET_DRIVER_DUMP :\r |
| 1129 | for (nl_iterator it(vendor_data); it.has_next(); it.next()) {\r |
| 1130 | if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN) {\r |
| 1131 | mBuffSize = it.get_u32();\r |
| 1132 | if (mBuff)\r |
| 1133 | free(mBuff);\r |
| 1134 | mBuff = (char *)malloc(mBuffSize);\r |
| 1135 | if (!mBuff) {\r |
| 1136 | ALOGE("Buffer allocation failed");\r |
| 1137 | return NL_SKIP;\r |
| 1138 | }\r |
| 1139 | WifiRequest request(familyId(), ifaceId());\r |
| 1140 | int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_DRIVER_MEM_DUMP);\r |
| 1141 | if (result != WIFI_SUCCESS) {\r |
| 1142 | ALOGE("Failed to create get driver memory dump request; result = %d", result);\r |
| 1143 | free(mBuff);\r |
| 1144 | return NL_SKIP;\r |
| 1145 | }\r |
| 1146 | nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);\r |
| 1147 | result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN, mBuffSize);\r |
| 1148 | if (result != WIFI_SUCCESS) {\r |
| 1149 | ALOGE("Failed to put get driver memory dump request; result = %d", result);\r |
| 1150 | return result;\r |
| 1151 | }\r |
| 1152 | result = request.put_u64(ENHANCE_LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA, (uint64_t)mBuff);\r |
| 1153 | if (result != WIFI_SUCCESS) {\r |
| 1154 | ALOGE("Failed to put get driver memory dump request; result = %d", result);\r |
| 1155 | return result;\r |
| 1156 | }\r |
| 1157 | request.attr_end(data);\r |
| 1158 | result = requestResponse(request);\r |
| 1159 | if (result != WIFI_SUCCESS) {\r |
| 1160 | ALOGE("Failed to register get driver momory dump response; result = %d", result);\r |
| 1161 | }\r |
| 1162 | } else if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA) {\r |
| 1163 | ALOGI("Initiating memory dump callback");\r |
| 1164 | if (mcallback.on_driver_memory_dump) {\r |
| 1165 | (*mcallback.on_driver_memory_dump)(mBuff, mBuffSize);\r |
| 1166 | }\r |
| 1167 | if (mBuff) {\r |
| 1168 | free(mBuff);\r |
| 1169 | mBuff = NULL;\r |
| 1170 | }\r |
| 1171 | } else {\r |
| 1172 | ALOGW("Ignoring invalid attribute type = %d, size = %d",\r |
| 1173 | it.get_type(), it.get_len());\r |
| 1174 | }\r |
| 1175 | }\r |
| 1176 | break;\r |
| 1177 | case GET_FW_VER:\r |
| 1178 | case GET_DRV_VER:\r |
| 1179 | case GET_RING_DATA:\r |
| 1180 | case GET_RING_STATUS:\r |
| 1181 | case GET_FEATURE:\r |
| 1182 | case START_RING_LOG:\r |
| 1183 | default:\r |
| 1184 | {\r |
| 1185 | ALOGW("Ignoring GetCmdType %d \n", mType);\r |
| 1186 | }\r |
| 1187 | }\r |
| 1188 | return NL_OK;\r |
| 1189 | }\r |
| 1190 | \r |
| 1191 | virtual int handleEvent(WifiEvent& event) {\r |
| 1192 | /* NO events! */\r |
| 1193 | return NL_SKIP;\r |
| 1194 | }\r |
| 1195 | };\r |
| 1196 | \r |
| 1197 | /* API to collect a firmware memory dump for a given iface */\r |
| 1198 | wifi_error wifi_get_firmware_memory_dump( wifi_interface_handle iface,\r |
| 1199 | wifi_firmware_memory_dump_handler handler)\r |
| 1200 | {\r |
| 1201 | MemoryDumpCommand *cmd = new MemoryDumpCommand(iface, handler, GET_FW_DUMP);\r |
| 1202 | NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r |
| 1203 | wifi_error result = (wifi_error)cmd->start();\r |
| 1204 | cmd->releaseRef();\r |
| 1205 | return result;\r |
| 1206 | }\r |
| 1207 | \r |
| 1208 | wifi_error wifi_get_driver_memory_dump(wifi_interface_handle iface,\r |
| 1209 | wifi_driver_memory_dump_callbacks callbacks)\r |
| 1210 | {\r |
| 1211 | MemoryDumpCommand *cmd = new MemoryDumpCommand(iface, callbacks, GET_DRIVER_DUMP);\r |
| 1212 | NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r |
| 1213 | wifi_error result = (wifi_error)cmd->start();\r |
| 1214 | cmd->releaseRef();\r |
| 1215 | return result;\r |
| 1216 | }\r |
| 1217 | class WifiLoggerCommand: public WifiCommand\r |
| 1218 | {\r |
| 1219 | WLAN_DRIVER_WAKE_REASON_CNT *mGetWakeStats;\r |
| 1220 | \r |
| 1221 | public:\r |
| 1222 | WifiLoggerCommand(wifi_interface_handle handle, WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt)\r |
| 1223 | : WifiCommand(handle, 0), mGetWakeStats(wifi_wake_reason_cnt)\r |
| 1224 | { }\r |
| 1225 | \r |
| 1226 | int createRequest(WifiRequest& request) {\r |
| 1227 | int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_WAKE_REASON_STATS);\r |
| 1228 | if (result < 0) {\r |
| 1229 | return result;\r |
| 1230 | }\r |
| 1231 | \r |
| 1232 | nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);\r |
| 1233 | \r |
| 1234 | result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_CMD_EVENT_WAKE_CNT_SZ, mGetWakeStats->cmd_event_wake_cnt_sz);\r |
| 1235 | if (result != WIFI_SUCCESS) {\r |
| 1236 | ALOGE("Failed to put wake_cnt_sz; result = %d", result);\r |
| 1237 | return result;\r |
| 1238 | }\r |
| 1239 | result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_SZ, mGetWakeStats->driver_fw_local_wake_cnt_sz);\r |
| 1240 | if (result != WIFI_SUCCESS) {\r |
| 1241 | ALOGE("Failed to put driver_fw_local_wake_cnt; result = %d", result);\r |
| 1242 | return result;\r |
| 1243 | }\r |
| 1244 | request.attr_end(data);\r |
| 1245 | return result;\r |
| 1246 | }\r |
| 1247 | \r |
| 1248 | int start() {\r |
| 1249 | ALOGD("Start get wake reason stats command\n");\r |
| 1250 | WifiRequest request(familyId(), ifaceId());\r |
| 1251 | int result = createRequest(request);\r |
| 1252 | if (result < 0) {\r |
| 1253 | ALOGE("Failed to create get wake reason stats request; result = %d\n", result);\r |
| 1254 | return result;\r |
| 1255 | }\r |
| 1256 | result = requestResponse(request);\r |
| 1257 | if (result != WIFI_SUCCESS) {\r |
| 1258 | ALOGE("Failed to register get wake reason stats response; result = %d\n", result);\r |
| 1259 | }\r |
| 1260 | return result;\r |
| 1261 | }\r |
| 1262 | \r |
| 1263 | int handleResponse(WifiEvent& reply) {\r |
| 1264 | int len = 0;\r |
| 1265 | ALOGD("In WifiLoggerCommand::handleResponse\n");\r |
| 1266 | \r |
| 1267 | if (reply.get_cmd() != NL80211_CMD_VENDOR) {\r |
| 1268 | ALOGI("Ignoring reply with cmd = %d", reply.get_cmd());\r |
| 1269 | return NL_SKIP;\r |
| 1270 | }\r |
| 1271 | nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);\r |
| 1272 | len = reply.get_vendor_data_len();\r |
| 1273 | if (vendor_data == NULL || len == 0) {\r |
| 1274 | ALOGE("No Debug data found");\r |
| 1275 | return NL_SKIP;\r |
| 1276 | }\r |
| 1277 | nl_iterator it(vendor_data);\r |
| 1278 | \r |
| 1279 | if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_TOTAL_CMD_EVENT_WAKE) {\r |
| 1280 | ALOGE("TOTAL_CMD_EVENT_WAKE not found %d", it.get_type());\r |
| 1281 | return NL_SKIP;\r |
| 1282 | }\r |
| 1283 | \r |
| 1284 | mGetWakeStats->total_cmd_event_wake = it.get_u32();\r |
| 1285 | it.next();\r |
| 1286 | \r |
| 1287 | if(mGetWakeStats->total_cmd_event_wake && mGetWakeStats->cmd_event_wake_cnt) {\r |
| 1288 | if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_CMD_EVENT_WAKE_CNT_PTR) {\r |
| 1289 | ALOGE("CMD_EVENT_WAKE_CNT_PTR not found %d", it.get_type());\r |
| 1290 | return NL_SKIP;\r |
| 1291 | }\r |
| 1292 | \r |
| 1293 | len = it.get_len();\r |
| 1294 | mGetWakeStats->cmd_event_wake_cnt_used = (len < mGetWakeStats->cmd_event_wake_cnt_sz) ? len : mGetWakeStats->cmd_event_wake_cnt_sz;\r |
| 1295 | memcpy(mGetWakeStats->cmd_event_wake_cnt, it.get_data(), mGetWakeStats->cmd_event_wake_cnt_used * sizeof(int));\r |
| 1296 | } else {\r |
| 1297 | mGetWakeStats->cmd_event_wake_cnt_used = 0;\r |
| 1298 | }\r |
| 1299 | \r |
| 1300 | it.next();\r |
| 1301 | \r |
| 1302 | if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_TOTAL_DRIVER_FW_LOCAL_WAKE) {\r |
| 1303 | ALOGE("TOTAL_DRIVER_FW_LOCAL_WAKE not found %d", it.get_type());\r |
| 1304 | return NL_SKIP;\r |
| 1305 | }\r |
| 1306 | \r |
| 1307 | mGetWakeStats->total_driver_fw_local_wake = it.get_u32();\r |
| 1308 | it.next();\r |
| 1309 | \r |
| 1310 | if(mGetWakeStats->total_driver_fw_local_wake && mGetWakeStats->driver_fw_local_wake_cnt) {\r |
| 1311 | if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_PTR) {\r |
| 1312 | ALOGE("DRIVER_FW_LOCAL_WAKE_CNT_PTR not found %d", it.get_type());\r |
| 1313 | return NL_SKIP;\r |
| 1314 | }\r |
| 1315 | \r |
| 1316 | len = it.get_len();\r |
| 1317 | mGetWakeStats->driver_fw_local_wake_cnt_used= (len < mGetWakeStats->driver_fw_local_wake_cnt_sz) ? len : mGetWakeStats->driver_fw_local_wake_cnt_sz;\r |
| 1318 | memcpy(mGetWakeStats->driver_fw_local_wake_cnt, it.get_data(), mGetWakeStats->driver_fw_local_wake_cnt_used * sizeof(int));\r |
| 1319 | } else {\r |
| 1320 | mGetWakeStats->driver_fw_local_wake_cnt_used= 0;\r |
| 1321 | }\r |
| 1322 | \r |
| 1323 | it.next();\r |
| 1324 | \r |
| 1325 | if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_TOTAL_RX_DATA_WAKE) {\r |
| 1326 | ALOGE("TOTAL_RX_DATA_WAKE not found %d", it.get_type());\r |
| 1327 | return NL_SKIP;\r |
| 1328 | }\r |
| 1329 | \r |
| 1330 | mGetWakeStats->total_rx_data_wake = it.get_u32();\r |
| 1331 | it.next();\r |
| 1332 | \r |
| 1333 | if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_RX_UNICAST_CNT) {\r |
| 1334 | ALOGE("RX_UNICAST_CNT not found %d", it.get_type());\r |
| 1335 | return NL_SKIP;\r |
| 1336 | }\r |
| 1337 | \r |
| 1338 | mGetWakeStats->rx_wake_details.rx_unicast_cnt = it.get_u32();\r |
| 1339 | it.next();\r |
| 1340 | \r |
| 1341 | if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_RX_MULTICAST_CNT) {\r |
| 1342 | ALOGE("RX_MULTICAST_CNT not found %d", it.get_type());\r |
| 1343 | return NL_SKIP;\r |
| 1344 | }\r |
| 1345 | \r |
| 1346 | mGetWakeStats->rx_wake_details.rx_multicast_cnt = it.get_u32();\r |
| 1347 | it.next();\r |
| 1348 | \r |
| 1349 | if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_RX_BROADCAST_CNT) {\r |
| 1350 | ALOGE("RX_BROADCAST_CNT not found %d", it.get_type());\r |
| 1351 | return NL_SKIP;\r |
| 1352 | }\r |
| 1353 | \r |
| 1354 | mGetWakeStats->rx_wake_details.rx_broadcast_cnt = it.get_u32();\r |
| 1355 | it.next();\r |
| 1356 | \r |
| 1357 | if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP_PKT) {\r |
| 1358 | ALOGE("ICMP_PKT not found %d", it.get_type());\r |
| 1359 | return NL_SKIP;\r |
| 1360 | }\r |
| 1361 | \r |
| 1362 | mGetWakeStats->rx_wake_pkt_classification_info .icmp_pkt = it.get_u32();\r |
| 1363 | it.next();\r |
| 1364 | \r |
| 1365 | if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_PKT) {\r |
| 1366 | ALOGE("ICMP6_PKT not found %d", it.get_type());\r |
| 1367 | return NL_SKIP;\r |
| 1368 | }\r |
| 1369 | \r |
| 1370 | mGetWakeStats->rx_wake_pkt_classification_info .icmp6_pkt = it.get_u32();\r |
| 1371 | it.next();\r |
| 1372 | \r |
| 1373 | if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_RA) {\r |
| 1374 | ALOGE("ICMP6_RA not found %d", it.get_type());\r |
| 1375 | return NL_SKIP;\r |
| 1376 | }\r |
| 1377 | \r |
| 1378 | mGetWakeStats->rx_wake_pkt_classification_info .icmp6_ra = it.get_u32();\r |
| 1379 | it.next();\r |
| 1380 | \r |
| 1381 | if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_NA) {\r |
| 1382 | ALOGE("ICMP6_NA not found %d", it.get_type());\r |
| 1383 | return NL_SKIP;\r |
| 1384 | }\r |
| 1385 | \r |
| 1386 | mGetWakeStats->rx_wake_pkt_classification_info .icmp6_na = it.get_u32();\r |
| 1387 | it.next();\r |
| 1388 | \r |
| 1389 | if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_NS) {\r |
| 1390 | ALOGE("ICMP6_NS not found %d", it.get_type());\r |
| 1391 | return NL_SKIP;\r |
| 1392 | }\r |
| 1393 | \r |
| 1394 | mGetWakeStats->rx_wake_pkt_classification_info .icmp6_ns = it.get_u32();\r |
| 1395 | it.next();\r |
| 1396 | \r |
| 1397 | if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP4_RX_MULTICAST_CNT) {\r |
| 1398 | ALOGE("ICMP4_RX_MULTICAST_CNT not found %d", it.get_type());\r |
| 1399 | return NL_SKIP;\r |
| 1400 | }\r |
| 1401 | \r |
| 1402 | mGetWakeStats->rx_multicast_wake_pkt_info.ipv4_rx_multicast_addr_cnt = it.get_u32();\r |
| 1403 | it.next();\r |
| 1404 | \r |
| 1405 | if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_RX_MULTICAST_CNT) {\r |
| 1406 | ALOGE("ICMP6_RX_MULTICAST_CNT not found %d", it.get_type());\r |
| 1407 | return NL_SKIP;\r |
| 1408 | }\r |
| 1409 | \r |
| 1410 | mGetWakeStats->rx_multicast_wake_pkt_info.ipv6_rx_multicast_addr_cnt = it.get_u32();\r |
| 1411 | it.next();\r |
| 1412 | \r |
| 1413 | if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_OTHER_RX_MULTICAST_CNT) {\r |
| 1414 | ALOGE("OTHER_RX_MULTICAST_CNT not found %d", it.get_type());\r |
| 1415 | return NL_SKIP;\r |
| 1416 | }\r |
| 1417 | \r |
| 1418 | mGetWakeStats->rx_multicast_wake_pkt_info.other_rx_multicast_addr_cnt = it.get_u32();\r |
| 1419 | \r |
| 1420 | return NL_OK;\r |
| 1421 | }\r |
| 1422 | \r |
| 1423 | int handleEvent(WifiEvent& event) {\r |
| 1424 | /* NO events to handle here! */\r |
| 1425 | return NL_SKIP;\r |
| 1426 | }\r |
| 1427 | };\r |
| 1428 | \r |
| 1429 | /* Function to get wake lock stats */\r |
| 1430 | wifi_error wifi_get_wake_reason_stats(wifi_interface_handle iface,\r |
| 1431 | WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt)\r |
| 1432 | {\r |
| 1433 | if(wifi_wake_reason_cnt) {\r |
| 1434 | WifiLoggerCommand *cmd = new WifiLoggerCommand(iface,wifi_wake_reason_cnt);\r |
| 1435 | NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r |
| 1436 | wifi_error result = (wifi_error)cmd->start();\r |
| 1437 | cmd->releaseRef();\r |
| 1438 | return result;\r |
| 1439 | } else {\r |
| 1440 | ALOGE("Reason cnt NULL");\r |
| 1441 | return WIFI_ERROR_INVALID_ARGS;\r |
| 1442 | }\r |
| 1443 | }\r |
| 1444 | \r |