[9610][7885] wlbt :Revert setScanningMacOui support as feature and only pass VTS.
[GitHub/MotorolaMobilityLLC/hardware-samsung_slsi-scsc_wifibt-wifi_hal.git] / wifi_logger.cpp
CommitLineData
cdc775c7
HG
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
30using namespace android;\r
31\r
32typedef 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
49typedef 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
90typedef 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
98typedef 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
109typedef enum {\r
110 PACKET_MONITOR_START,\r
111 TX_PACKET_FATE,\r
112 RX_PACKET_FATE,\r
113} PktFateReqType;\r
114\r
115class DebugCommand : public WifiCommand\r
116{\r
49d0342d 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
cdc775c7
HG
127 GetCmdType mType;\r
128\r
129public:\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 int len = reply.get_vendor_data_len();\r
384\r
385 ALOGD("len = %d, expected len = %d", len, sizeof(unsigned int));\r
386 memcpy(mSupport, data, sizeof(unsigned int));\r
387 break;\r
388 }\r
389\r
390 default:\r
391 ALOGW("Unknown Debug command");\r
392 }\r
393 return NL_OK;\r
394 }\r
395\r
396 virtual int handleEvent(WifiEvent& event) {\r
397 /* NO events! */\r
398 return NL_SKIP;\r
399 }\r
400};\r
401\r
402/* API to get supportable feature */\r
403wifi_error wifi_get_logger_supported_feature_set(wifi_interface_handle iface,\r
404 unsigned int *support)\r
405{\r
406 if (support) {\r
407 DebugCommand *cmd = new DebugCommand(iface, support, GET_FEATURE);\r
408 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r
409 wifi_error result = (wifi_error)cmd->start();\r
410 cmd->releaseRef();\r
411 return result;\r
412 } else {\r
413 ALOGE("Get support buffer NULL");\r
414 return WIFI_ERROR_INVALID_ARGS;\r
415 }\r
416}\r
417\r
418/* API to get the status of all ring buffers supported by driver */\r
419wifi_error wifi_get_ring_buffers_status(wifi_interface_handle iface,\r
420 u32 *num_rings, wifi_ring_buffer_status *status)\r
421{\r
422 if (status && num_rings) {\r
423 DebugCommand *cmd = new DebugCommand(iface, num_rings, status, GET_RING_STATUS);\r
424 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r
425 wifi_error result = (wifi_error)cmd->start();\r
426 cmd->releaseRef();\r
427 return result;\r
428 } else {\r
429 ALOGE("Ring status buffer NULL");\r
430 return WIFI_ERROR_INVALID_ARGS;\r
431 }\r
432}\r
433\r
434/* API to collect driver records */\r
435wifi_error wifi_get_ring_data(wifi_interface_handle iface, char *ring_name)\r
436{\r
437 DebugCommand *cmd = new DebugCommand(iface, ring_name, GET_RING_DATA);\r
438 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r
439 wifi_error result = (wifi_error)cmd->start();\r
440 cmd->releaseRef();\r
441 return result;\r
442}\r
443\r
444wifi_error wifi_start_logging(wifi_interface_handle iface, u32 verbose_level,\r
445 u32 flags, u32 max_interval_sec, u32 min_data_size, char *ring_name)\r
446{\r
447 if (ring_name) {\r
448 DebugCommand *cmd = new DebugCommand(iface, verbose_level, flags, max_interval_sec,\r
449 min_data_size, ring_name, START_RING_LOG);\r
450 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r
451 wifi_error result = (wifi_error)cmd->start();\r
452 cmd->releaseRef();\r
453 return result;\r
454 } else {\r
455 ALOGE("Ring name NULL");\r
456 return WIFI_ERROR_INVALID_ARGS;\r
457 }\r
458}\r
459\r
460/* API to collect a firmware version string */\r
461wifi_error wifi_get_firmware_version(wifi_interface_handle iface, char *buffer,\r
462 int buffer_size)\r
463{\r
464 if (buffer && (buffer_size > 0)) {\r
465 DebugCommand *cmd = new DebugCommand(iface, buffer, &buffer_size, GET_FW_VER);\r
466 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r
467 wifi_error result = (wifi_error)cmd->start();\r
468 cmd->releaseRef();\r
469 return result;\r
470 } else {\r
471 ALOGE("FW version buffer NULL");\r
472 return WIFI_ERROR_INVALID_ARGS;\r
473 }\r
474}\r
475\r
476/* API to collect a driver version string */\r
477wifi_error wifi_get_driver_version(wifi_interface_handle iface, char *buffer, int buffer_size)\r
478{\r
479 if (buffer && (buffer_size > 0)) {\r
480 DebugCommand *cmd = new DebugCommand(iface, buffer, &buffer_size, GET_DRV_VER);\r
481 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r
482 wifi_error result = (wifi_error)cmd->start();\r
483 cmd->releaseRef();\r
484 return result;\r
485 } else {\r
486 ALOGE("Driver version buffer NULL");\r
487 return WIFI_ERROR_INVALID_ARGS;\r
488 }\r
489}\r
490\r
491\r
492///////////////////////////////////////////////////////////////////////////////\r
493class SetLogHandler : public WifiCommand\r
494{\r
495 wifi_ring_buffer_data_handler mHandler;\r
496\r
497public:\r
498 SetLogHandler(wifi_interface_handle iface, int id, wifi_ring_buffer_data_handler handler)\r
499 : WifiCommand(iface, id), mHandler(handler)\r
500 { }\r
501\r
502 int start() {\r
503 ALOGV("Register loghandler");\r
504 registerVendorHandler(GOOGLE_OUI, ENHANCE_LOGGER_RING_EVENT);\r
505 return WIFI_SUCCESS;\r
506 }\r
507\r
508 virtual int cancel() {\r
509 /* Send a command to driver to stop generating logging events */\r
510 ALOGV("Clear loghandler");\r
511\r
512 /* unregister event handler */\r
513 unregisterVendorHandler(GOOGLE_OUI, ENHANCE_LOGGER_RING_EVENT);\r
514\r
515 WifiRequest request(familyId(), ifaceId());\r
516 int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_RESET_LOGGING);\r
517 if (result != WIFI_SUCCESS) {\r
518 ALOGE("failed to create reset request; result = %d", result);\r
519 return result;\r
520 }\r
521\r
522 result = requestResponse(request);\r
523 if (result != WIFI_SUCCESS) {\r
524 ALOGE("failed to request reset; result = %d", result);\r
525 return result;\r
526 }\r
527\r
528 ALOGD("Success to clear loghandler");\r
529 return WIFI_SUCCESS;\r
530 }\r
531\r
532 virtual int handleEvent(WifiEvent& event) {\r
533 char *buffer = NULL;\r
534 int buffer_size = 0;\r
535\r
536 // ALOGD("In SetLogHandler::handleEvent");\r
537 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);\r
538 int len = event.get_vendor_data_len();\r
539 int event_id = event.get_vendor_subcmd();\r
540 // ALOGI("Got Logger event: %d", event_id);\r
541\r
542 if (vendor_data == NULL || len == 0) {\r
543 ALOGE("No Debug data found");\r
544 return NL_SKIP;\r
545 }\r
546\r
547 if(event_id == ENHANCE_LOGGER_RING_EVENT) {\r
548 wifi_ring_buffer_status status;\r
549 memset(&status, 0, sizeof(status));\r
550\r
551 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {\r
552 if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_RING_STATUS) {\r
553 memcpy(&status, it.get_data(), sizeof(status));\r
554 } else if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_RING_DATA) {\r
555 buffer_size = it.get_len();\r
556 buffer = (char *)it.get_data();\r
557 } else {\r
558 ALOGW("Ignoring invalid attribute type = %d, size = %d",\r
559 it.get_type(), it.get_len());\r
560 }\r
561 }\r
562\r
563 // ALOGI("Retrieved Debug data");\r
564 if (mHandler.on_ring_buffer_data) {\r
565 (*mHandler.on_ring_buffer_data)((char *)status.name, buffer, buffer_size,\r
566 &status);\r
567 }\r
568 } else {\r
569 ALOGE("Unknown Event");\r
570 return NL_SKIP;\r
571 }\r
572 return NL_OK;\r
573 }\r
574};\r
575\r
576wifi_error wifi_set_log_handler(wifi_request_id id, wifi_interface_handle iface,\r
577 wifi_ring_buffer_data_handler handler)\r
578{\r
579 wifi_handle handle = getWifiHandle(iface);\r
580 ALOGV("Loghandler start, handle = %p", handle);\r
581\r
582 SetLogHandler *cmd = new SetLogHandler(iface, id, handler);\r
583 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r
584 wifi_error result = wifi_register_cmd(handle, id, cmd);\r
585 if (result != WIFI_SUCCESS) {\r
586 cmd->releaseRef();\r
587 return result;\r
588 }\r
589 result = (wifi_error)cmd->start();\r
590 if (result != WIFI_SUCCESS) {\r
591 wifi_unregister_cmd(handle, id);\r
592 cmd->releaseRef();\r
593 return result;\r
594 }\r
595 return result;\r
596}\r
597\r
598wifi_error wifi_reset_log_handler(wifi_request_id id, wifi_interface_handle iface)\r
599{\r
600 wifi_handle handle = getWifiHandle(iface);\r
601 ALOGV("Loghandler reset, wifi_request_id = %d, handle = %p", id, handle);\r
602\r
603 if (id == -1) {\r
604 wifi_ring_buffer_data_handler handler;\r
605 memset(&handler, 0, sizeof(handler));\r
606\r
607 SetLogHandler *cmd = new SetLogHandler(iface, id, handler);\r
608 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r
609 cmd->cancel();\r
610 cmd->releaseRef();\r
611 return WIFI_SUCCESS;\r
612 }\r
613\r
614 return wifi_cancel_cmd(id, iface);\r
615}\r
616\r
617///////////////////////////////////////////////////////////////////////////////\r
618class SetAlertHandler : public WifiCommand\r
619{\r
620 wifi_alert_handler mHandler;\r
621 int mBuffSize;\r
622 char *mBuff;\r
623 int mErrCode;\r
624\r
625public:\r
626 SetAlertHandler(wifi_interface_handle iface, int id, wifi_alert_handler handler)\r
627 : WifiCommand(iface, id), mHandler(handler), mBuffSize(0), mBuff(NULL),\r
628 mErrCode(0)\r
629 { }\r
630\r
631 int start() {\r
632 ALOGV("Start Alerting");\r
633 registerVendorHandler(GOOGLE_OUI, ENHANCE_LOGGER_MEM_DUMP_EVENT);\r
634 return WIFI_SUCCESS;\r
635 }\r
636\r
637 virtual int cancel() {\r
638 ALOGV("Clear alerthandler");\r
639\r
640 /* unregister alert handler */\r
641 unregisterVendorHandler(GOOGLE_OUI, ENHANCE_LOGGER_MEM_DUMP_EVENT);\r
642 wifi_unregister_cmd(wifiHandle(), id());\r
643 ALOGD("Success to clear alerthandler");\r
644 return WIFI_SUCCESS;\r
645 }\r
646\r
647 virtual int handleResponse(WifiEvent& reply) {\r
648 ALOGD("In SetAlertHandler::handleResponse");\r
649\r
650 if (reply.get_cmd() != NL80211_CMD_VENDOR) {\r
651 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());\r
652 return NL_SKIP;\r
653 }\r
654\r
655 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);\r
656 int len = reply.get_vendor_data_len();\r
657\r
658 ALOGD("len = %d", len);\r
659 if (vendor_data == NULL || len == 0) {\r
660 ALOGE("no vendor data in memory dump response; ignoring it");\r
661 return NL_SKIP;\r
662 }\r
663\r
664 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {\r
665 if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_DATA) {\r
666 ALOGI("Initiating alert callback");\r
667 if (mHandler.on_alert) {\r
668 (*mHandler.on_alert)(id(), mBuff, mBuffSize, mErrCode);\r
669 }\r
670 if (mBuff) {\r
671 free(mBuff);\r
672 mBuff = NULL;\r
673 }\r
674 }\r
675 }\r
676 return NL_OK;\r
677 }\r
678\r
679 virtual int handleEvent(WifiEvent& event) {\r
680 wifi_ring_buffer_id ring_id;\r
681 char *buffer = NULL;\r
682 int buffer_size = 0;\r
683\r
684\r
685 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);\r
686 int len = event.get_vendor_data_len();\r
687 int event_id = event.get_vendor_subcmd();\r
688 ALOGI("Got event: %d", event_id);\r
689\r
690 if (vendor_data == NULL || len == 0) {\r
691 ALOGE("No Debug data found");\r
692 return NL_SKIP;\r
693 }\r
694\r
695 if (event_id == ENHANCE_LOGGER_MEM_DUMP_EVENT) {\r
696 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {\r
697 if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_LEN) {\r
698 mBuffSize = it.get_u32();\r
699 } else if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_RING_DATA) {\r
700 buffer_size = it.get_len();\r
701 buffer = (char *)it.get_data();\r
702 /*\r
703 } else if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_FW_ERR_CODE) {\r
704 mErrCode = it.get_u32();\r
705 */\r
706 } else {\r
707 ALOGW("Ignoring invalid attribute type = %d, size = %d",\r
708 it.get_type(), it.get_len());\r
709 }\r
710 }\r
711 if (mBuffSize) {\r
712 ALOGD("dump size: %d meta data size: %d", mBuffSize, buffer_size);\r
713 if (mBuff) free(mBuff);\r
714 mBuff = (char *)malloc(mBuffSize + buffer_size);\r
715 if (!mBuff) {\r
716 ALOGE("Buffer allocation failed");\r
717 return NL_SKIP;\r
718 }\r
719 memcpy(mBuff, buffer, buffer_size);\r
720\r
721 WifiRequest request(familyId(), ifaceId());\r
722 int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_MEM_DUMP_EVENT);\r
723 if (result != WIFI_SUCCESS) {\r
724 ALOGE("Failed to create get memory dump request; result = %d", result);\r
725 free(mBuff);\r
726 return NL_SKIP;\r
727 }\r
728 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);\r
729 result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_LEN, mBuffSize);\r
730 if (result != WIFI_SUCCESS) {\r
731 ALOGE("Failed to put get memory dump request; result = %d", result);\r
732 return result;\r
733 }\r
734\r
735 result = request.put_u64(ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_DATA,\r
736 (uint64_t)(mBuff+buffer_size));\r
737 if (result != WIFI_SUCCESS) {\r
738 ALOGE("Failed to put get memory dump request; result = %d", result);\r
739 return result;\r
740 }\r
741\r
742 request.attr_end(data);\r
743 mBuffSize += buffer_size;\r
744\r
745 result = requestResponse(request);\r
746\r
747 if (result != WIFI_SUCCESS) {\r
748 ALOGE("Failed to register get momory dump response; result = %d", result);\r
749 }\r
750 } else {\r
751 ALOGE("dump event missing dump length attribute");\r
752 return NL_SKIP;\r
753 }\r
754 }\r
755 return NL_OK;\r
756 }\r
757};\r
758\r
759wifi_error wifi_set_alert_handler(wifi_request_id id, wifi_interface_handle iface,\r
760 wifi_alert_handler handler)\r
761{\r
762 wifi_handle handle = getWifiHandle(iface);\r
763 ALOGV("Alerthandler start, handle = %p", handle);\r
764\r
765 SetAlertHandler *cmd = new SetAlertHandler(iface, id, handler);\r
766 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r
767 wifi_error result = wifi_register_cmd(handle, id, cmd);\r
768 if (result != WIFI_SUCCESS) {\r
769 cmd->releaseRef();\r
770 return result;\r
771 }\r
772 result = (wifi_error)cmd->start();\r
773 if (result != WIFI_SUCCESS) {\r
774 wifi_unregister_cmd(handle, id);\r
775 cmd->releaseRef();\r
776 return result;\r
777 }\r
778 return result;\r
779}\r
780\r
781wifi_error wifi_reset_alert_handler(wifi_request_id id, wifi_interface_handle iface)\r
782{\r
783 wifi_handle handle = getWifiHandle(iface);\r
784 ALOGV("Alerthandler reset, wifi_request_id = %d, handle = %p", id, handle);\r
785\r
786 if (id == -1) {\r
787 wifi_alert_handler handler;\r
788 memset(&handler, 0, sizeof(handler));\r
789\r
790 SetAlertHandler *cmd = new SetAlertHandler(iface, id, handler);\r
791 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r
792 cmd->cancel();\r
793 cmd->releaseRef();\r
794 return WIFI_SUCCESS;\r
795 }\r
796\r
797 return wifi_cancel_cmd(id, iface);\r
798}\r
799\r
800\r
801class PacketFateCommand: public WifiCommand\r
802{\r
49d0342d 803 void *mReportBufs = NULL;\r
804 size_t mNoReqFates = 0;\r
805 size_t *mNoProvidedFates = NULL;\r
cdc775c7
HG
806 PktFateReqType mReqType;\r
807\r
808public:\r
809 PacketFateCommand(wifi_interface_handle handle)\r
810 : WifiCommand(handle, 0), mReqType(PACKET_MONITOR_START)\r
811 { }\r
812\r
813 PacketFateCommand(wifi_interface_handle handle, wifi_tx_report *tx_report_bufs,\r
814 size_t n_requested_fates, size_t *n_provided_fates)\r
815 : WifiCommand(handle, 0), mReportBufs(tx_report_bufs),\r
816 mNoReqFates(n_requested_fates), mNoProvidedFates(n_provided_fates),\r
817 mReqType(TX_PACKET_FATE)\r
818 { }\r
819\r
820 PacketFateCommand(wifi_interface_handle handle, wifi_rx_report *rx_report_bufs,\r
821 size_t n_requested_fates, size_t *n_provided_fates)\r
822 : WifiCommand(handle, 0), mReportBufs(rx_report_bufs),\r
823 mNoReqFates(n_requested_fates), mNoProvidedFates(n_provided_fates),\r
824 mReqType(RX_PACKET_FATE)\r
825 { }\r
826\r
827 int createRequest(WifiRequest& request) {\r
828 if (mReqType == TX_PACKET_FATE) {\r
829 ALOGD("%s Get Tx packet fate request\n", __FUNCTION__);\r
830 return createTxPktFateRequest(request);\r
831 } else if (mReqType == RX_PACKET_FATE) {\r
832 ALOGD("%s Get Rx packet fate request\n", __FUNCTION__);\r
833 return createRxPktFateRequest(request);\r
834 } else if (mReqType == PACKET_MONITOR_START) {\r
835 ALOGD("%s Monitor packet fate request\n", __FUNCTION__);\r
836 return createMonitorPktFateRequest(request);\r
837 } else {\r
838 ALOGE("%s Unknown packet fate request\n", __FUNCTION__);\r
839 return WIFI_ERROR_NOT_SUPPORTED;\r
840 }\r
841 return WIFI_SUCCESS;\r
842 }\r
843\r
844 int createMonitorPktFateRequest(WifiRequest& request) {\r
845 int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_START_PKT_FATE_MONITORING);\r
846 if (result < 0) {\r
847 return result;\r
848 }\r
849\r
850 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);\r
851 request.attr_end(data);\r
852 return result;\r
853 }\r
854\r
855 int createTxPktFateRequest(WifiRequest& request) {\r
856 int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_TX_PKT_FATES);\r
857 if (result < 0) {\r
858 return result;\r
859 }\r
860\r
861 memset(mReportBufs, 0, (mNoReqFates * sizeof(wifi_tx_report)));\r
862 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);\r
863 result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_PKT_FATE_NUM, mNoReqFates);\r
864 if (result < 0) {\r
865 return result;\r
866 }\r
867 result = request.put_u64(ENHANCE_LOGGER_ATTRIBUTE_PKT_FATE_DATA, (uint64_t)mReportBufs);\r
868 if (result < 0) {\r
869 return result;\r
870 }\r
871 request.attr_end(data);\r
872 return result;\r
873 }\r
874\r
875 int createRxPktFateRequest(WifiRequest& request) {\r
876 int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_RX_PKT_FATES);\r
877 if (result < 0) {\r
878 return result;\r
879 }\r
880\r
881 memset(mReportBufs, 0, (mNoReqFates * sizeof(wifi_rx_report)));\r
882 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);\r
883 result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_PKT_FATE_NUM, mNoReqFates);\r
884 if (result < 0) {\r
885 return result;\r
886 }\r
887 result = request.put_u64(ENHANCE_LOGGER_ATTRIBUTE_PKT_FATE_DATA, (uint64_t)mReportBufs);\r
888 if (result < 0) {\r
889 return result;\r
890 }\r
891 request.attr_end(data);\r
892 return result;\r
893 }\r
894\r
895 int start() {\r
896 ALOGD("Start get packet fate command\n");\r
897 WifiRequest request(familyId(), ifaceId());\r
898\r
899 int result = createRequest(request);\r
900 if (result < 0) {\r
901 ALOGE("Failed to create get pkt fate request; result = %d\n", result);\r
902 return result;\r
903 }\r
904\r
905 result = requestResponse(request);\r
906 if (result != WIFI_SUCCESS) {\r
907 ALOGE("Failed to register get pkt fate response; result = %d\n", result);\r
908 }\r
909 return result;\r
910 }\r
911\r
912 int handleResponse(WifiEvent& reply) {\r
913 ALOGD("In GetPktFateCommand::handleResponse\n");\r
914\r
915 if (reply.get_cmd() != NL80211_CMD_VENDOR) {\r
916 ALOGI("Ignoring reply with cmd = %d", reply.get_cmd());\r
917 return NL_SKIP;\r
918 }\r
919\r
920 int id = reply.get_vendor_id();\r
921 int subcmd = reply.get_vendor_subcmd();\r
922 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);\r
923 int len = reply.get_vendor_data_len();\r
924\r
925 ALOGI("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);\r
926\r
927 if (mReqType == TX_PACKET_FATE) {\r
928 ALOGI("Response recieved for get TX pkt fate command\n");\r
929 } else if (mReqType == RX_PACKET_FATE) {\r
930 ALOGI("Response recieved for get RX pkt fate command\n");\r
931 } else if (mReqType == PACKET_MONITOR_START) {\r
932 ALOGI("Response recieved for monitor pkt fate command\n");\r
933 return NL_OK;\r
934 } else {\r
935 ALOGE("Response recieved for unknown pkt fate command\n");\r
936 return NL_SKIP;\r
937 }\r
938\r
939 if (vendor_data == NULL || len == 0) {\r
940 ALOGE("no vendor data in GetPktFateCommand response; ignoring it\n");\r
941 return NL_SKIP;\r
942 }\r
943\r
944 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {\r
945 if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_PKT_FATE_NUM) {\r
946 *mNoProvidedFates = it.get_u32();\r
947 ALOGI("No: of pkt fates provided is %d\n", *mNoProvidedFates);\r
948 } else {\r
949 ALOGE("Ignoring invalid attribute type = %d, size = %d\n",\r
950 it.get_type(), it.get_len());\r
951 }\r
952 }\r
953\r
954 return NL_OK;\r
955 }\r
956\r
957 int handleEvent(WifiEvent& event) {\r
958 /* NO events to handle here! */\r
959 return NL_SKIP;\r
960 }\r
961};\r
962\r
963wifi_error wifi_start_pkt_fate_monitoring(wifi_interface_handle handle)\r
964{\r
965 PacketFateCommand *cmd = new PacketFateCommand(handle);\r
966 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r
967 wifi_error result = (wifi_error)cmd->start();\r
968 cmd->releaseRef();\r
969 return result;\r
970}\r
971\r
972wifi_error wifi_get_tx_pkt_fates(wifi_interface_handle handle,\r
973 wifi_tx_report *tx_report_bufs, size_t n_requested_fates,\r
974 size_t *n_provided_fates)\r
975{\r
976 PacketFateCommand *cmd = new PacketFateCommand(handle, tx_report_bufs,\r
977 n_requested_fates, n_provided_fates);\r
978 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r
979 wifi_error result = (wifi_error)cmd->start();\r
980 cmd->releaseRef();\r
981 return result;\r
982}\r
983\r
984wifi_error wifi_get_rx_pkt_fates(wifi_interface_handle handle,\r
985 wifi_rx_report *rx_report_bufs, size_t n_requested_fates,\r
986 size_t *n_provided_fates)\r
987{\r
988 PacketFateCommand *cmd = new PacketFateCommand(handle, rx_report_bufs,\r
989 n_requested_fates, n_provided_fates);\r
990 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r
991 wifi_error result = (wifi_error)cmd->start();\r
992 cmd->releaseRef();\r
993 return result;\r
994}\r
995\r
996class 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
49d0342d 1003 \r
cdc775c7
HG
1004public:\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
49d0342d 1007 { \r
1008 memset(&mHandler,0,sizeof(wifi_firmware_memory_dump_handler));\r
1009 }\r
cdc775c7
HG
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
49d0342d 1013 {\r
1014 memset(&mcallback,0,sizeof(wifi_driver_memory_dump_callbacks));\r
1015 }\r
cdc775c7
HG
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 case GET_DRIVER_DUMP :\r
1128 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {\r
1129 if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN) {\r
1130 mBuffSize = it.get_u32();\r
1131 if (mBuff)\r
1132 free(mBuff);\r
1133 mBuff = (char *)malloc(mBuffSize);\r
1134 if (!mBuff) {\r
1135 ALOGE("Buffer allocation failed");\r
1136 return NL_SKIP;\r
1137 }\r
1138 WifiRequest request(familyId(), ifaceId());\r
1139 int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_DRIVER_MEM_DUMP);\r
1140 if (result != WIFI_SUCCESS) {\r
1141 ALOGE("Failed to create get driver memory dump request; result = %d", result);\r
1142 free(mBuff);\r
1143 return NL_SKIP;\r
1144 }\r
1145 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);\r
1146 result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN, mBuffSize);\r
1147 if (result != WIFI_SUCCESS) {\r
1148 ALOGE("Failed to put get driver memory dump request; result = %d", result);\r
1149 return result;\r
1150 }\r
1151 result = request.put_u64(ENHANCE_LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA, (uint64_t)mBuff);\r
1152 if (result != WIFI_SUCCESS) {\r
1153 ALOGE("Failed to put get driver memory dump request; result = %d", result);\r
1154 return result;\r
1155 }\r
1156 request.attr_end(data);\r
1157 result = requestResponse(request);\r
1158 if (result != WIFI_SUCCESS) {\r
1159 ALOGE("Failed to register get driver momory dump response; result = %d", result);\r
1160 }\r
1161 } else if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA) {\r
1162 ALOGI("Initiating memory dump callback");\r
1163 if (mcallback.on_driver_memory_dump) {\r
1164 (*mcallback.on_driver_memory_dump)(mBuff, mBuffSize);\r
1165 }\r
1166 if (mBuff) {\r
1167 free(mBuff);\r
1168 mBuff = NULL;\r
1169 }\r
1170 } else {\r
1171 ALOGW("Ignoring invalid attribute type = %d, size = %d",\r
1172 it.get_type(), it.get_len());\r
1173 }\r
1174 }\r
1175 }\r
1176 return NL_OK;\r
1177 }\r
1178\r
1179 virtual int handleEvent(WifiEvent& event) {\r
1180 /* NO events! */\r
1181 return NL_SKIP;\r
1182 }\r
1183};\r
1184\r
1185/* API to collect a firmware memory dump for a given iface */\r
1186wifi_error wifi_get_firmware_memory_dump( wifi_interface_handle iface,\r
1187 wifi_firmware_memory_dump_handler handler)\r
1188{\r
1189 MemoryDumpCommand *cmd = new MemoryDumpCommand(iface, handler, GET_FW_DUMP);\r
1190 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r
1191 wifi_error result = (wifi_error)cmd->start();\r
1192 cmd->releaseRef();\r
1193 return result;\r
1194}\r
1195\r
1196wifi_error wifi_get_driver_memory_dump(wifi_interface_handle iface,\r
1197 wifi_driver_memory_dump_callbacks callbacks)\r
1198{\r
1199 MemoryDumpCommand *cmd = new MemoryDumpCommand(iface, callbacks, GET_DRIVER_DUMP);\r
1200 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r
1201 wifi_error result = (wifi_error)cmd->start();\r
1202 cmd->releaseRef();\r
1203 return result;\r
1204}\r
1205class WifiLoggerCommand: public WifiCommand\r
1206{\r
1207 WLAN_DRIVER_WAKE_REASON_CNT *mGetWakeStats;\r
1208\r
1209public:\r
1210 WifiLoggerCommand(wifi_interface_handle handle, WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt)\r
1211 : WifiCommand(handle, 0), mGetWakeStats(wifi_wake_reason_cnt)\r
1212 { }\r
1213\r
1214 int createRequest(WifiRequest& request) {\r
1215 int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_WAKE_REASON_STATS);\r
1216 if (result < 0) {\r
1217 return result;\r
1218 }\r
1219\r
1220 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);\r
1221\r
1222 result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_CMD_EVENT_WAKE_CNT_SZ, mGetWakeStats->cmd_event_wake_cnt_sz);\r
1223 if (result != WIFI_SUCCESS) {\r
1224 ALOGE("Failed to put wake_cnt_sz; result = %d", result);\r
1225 return result;\r
1226 }\r
1227 result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_SZ, mGetWakeStats->driver_fw_local_wake_cnt_sz);\r
1228 if (result != WIFI_SUCCESS) {\r
1229 ALOGE("Failed to put driver_fw_local_wake_cnt; result = %d", result);\r
1230 return result;\r
1231 }\r
1232 request.attr_end(data);\r
1233 return result;\r
1234 }\r
1235\r
1236 int start() {\r
1237 ALOGD("Start get wake reason stats command\n");\r
1238 WifiRequest request(familyId(), ifaceId());\r
1239 int result = createRequest(request);\r
1240 if (result < 0) {\r
1241 ALOGE("Failed to create get wake reason stats request; result = %d\n", result);\r
1242 return result;\r
1243 }\r
1244 result = requestResponse(request);\r
1245 if (result != WIFI_SUCCESS) {\r
1246 ALOGE("Failed to register get wake reason stats response; result = %d\n", result);\r
1247 }\r
1248 return result;\r
1249 }\r
1250\r
1251 int handleResponse(WifiEvent& reply) {\r
1252 int len = 0;\r
1253 ALOGD("In WifiLoggerCommand::handleResponse\n");\r
1254\r
1255 if (reply.get_cmd() != NL80211_CMD_VENDOR) {\r
1256 ALOGI("Ignoring reply with cmd = %d", reply.get_cmd());\r
1257 return NL_SKIP;\r
1258 }\r
1259 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);\r
1260 len = reply.get_vendor_data_len();\r
1261 if (vendor_data == NULL || len == 0) {\r
1262 ALOGE("No Debug data found");\r
1263 return NL_SKIP;\r
1264 }\r
1265 nl_iterator it(vendor_data);\r
1266\r
1267 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_TOTAL_CMD_EVENT_WAKE) {\r
1268 ALOGE("TOTAL_CMD_EVENT_WAKE not found %d", it.get_type());\r
1269 return NL_SKIP;\r
1270 }\r
1271\r
1272 mGetWakeStats->total_cmd_event_wake = it.get_u32();\r
1273 it.next();\r
1274\r
1275 if(mGetWakeStats->total_cmd_event_wake && mGetWakeStats->cmd_event_wake_cnt) {\r
1276 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_CMD_EVENT_WAKE_CNT_PTR) {\r
1277 ALOGE("CMD_EVENT_WAKE_CNT_PTR not found %d", it.get_type());\r
1278 return NL_SKIP;\r
1279 }\r
1280\r
1281 len = it.get_len();\r
1282 mGetWakeStats->cmd_event_wake_cnt_used = (len < mGetWakeStats->cmd_event_wake_cnt_sz) ? len : mGetWakeStats->cmd_event_wake_cnt_sz;\r
1283 memcpy(mGetWakeStats->cmd_event_wake_cnt, it.get_data(), mGetWakeStats->cmd_event_wake_cnt_used * sizeof(int));\r
1284 } else {\r
1285 mGetWakeStats->cmd_event_wake_cnt_used = 0;\r
1286 }\r
1287\r
1288 it.next();\r
1289\r
1290 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_TOTAL_DRIVER_FW_LOCAL_WAKE) {\r
1291 ALOGE("TOTAL_DRIVER_FW_LOCAL_WAKE not found %d", it.get_type());\r
1292 return NL_SKIP;\r
1293 }\r
1294\r
1295 mGetWakeStats->total_driver_fw_local_wake = it.get_u32();\r
1296 it.next();\r
1297\r
1298 if(mGetWakeStats->total_driver_fw_local_wake && mGetWakeStats->driver_fw_local_wake_cnt) {\r
1299 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_PTR) {\r
1300 ALOGE("DRIVER_FW_LOCAL_WAKE_CNT_PTR not found %d", it.get_type());\r
1301 return NL_SKIP;\r
1302 }\r
1303\r
1304 len = it.get_len();\r
1305 mGetWakeStats->driver_fw_local_wake_cnt_used= (len < mGetWakeStats->driver_fw_local_wake_cnt_sz) ? len : mGetWakeStats->driver_fw_local_wake_cnt_sz;\r
1306 memcpy(mGetWakeStats->driver_fw_local_wake_cnt, it.get_data(), mGetWakeStats->driver_fw_local_wake_cnt_used * sizeof(int));\r
1307 } else {\r
1308 mGetWakeStats->driver_fw_local_wake_cnt_used= 0;\r
1309 }\r
1310\r
1311 it.next();\r
1312\r
1313 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_TOTAL_RX_DATA_WAKE) {\r
1314 ALOGE("TOTAL_RX_DATA_WAKE not found %d", it.get_type());\r
1315 return NL_SKIP;\r
1316 }\r
1317\r
1318 mGetWakeStats->total_rx_data_wake = it.get_u32();\r
1319 it.next();\r
1320\r
1321 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_RX_UNICAST_CNT) {\r
1322 ALOGE("RX_UNICAST_CNT not found %d", it.get_type());\r
1323 return NL_SKIP;\r
1324 }\r
1325\r
1326 mGetWakeStats->rx_wake_details.rx_unicast_cnt = it.get_u32();\r
1327 it.next();\r
1328\r
1329 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_RX_MULTICAST_CNT) {\r
1330 ALOGE("RX_MULTICAST_CNT not found %d", it.get_type());\r
1331 return NL_SKIP;\r
1332 }\r
1333\r
1334 mGetWakeStats->rx_wake_details.rx_multicast_cnt = it.get_u32();\r
1335 it.next();\r
1336\r
1337 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_RX_BROADCAST_CNT) {\r
1338 ALOGE("RX_BROADCAST_CNT not found %d", it.get_type());\r
1339 return NL_SKIP;\r
1340 }\r
1341\r
1342 mGetWakeStats->rx_wake_details.rx_broadcast_cnt = it.get_u32();\r
1343 it.next();\r
1344\r
1345 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP_PKT) {\r
1346 ALOGE("ICMP_PKT not found %d", it.get_type());\r
1347 return NL_SKIP;\r
1348 }\r
1349\r
1350 mGetWakeStats->rx_wake_pkt_classification_info .icmp_pkt = it.get_u32();\r
1351 it.next();\r
1352\r
1353 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_PKT) {\r
1354 ALOGE("ICMP6_PKT not found %d", it.get_type());\r
1355 return NL_SKIP;\r
1356 }\r
1357\r
1358 mGetWakeStats->rx_wake_pkt_classification_info .icmp6_pkt = it.get_u32();\r
1359 it.next();\r
1360\r
1361 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_RA) {\r
1362 ALOGE("ICMP6_RA not found %d", it.get_type());\r
1363 return NL_SKIP;\r
1364 }\r
1365\r
1366 mGetWakeStats->rx_wake_pkt_classification_info .icmp6_ra = it.get_u32();\r
1367 it.next();\r
1368\r
1369 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_NA) {\r
1370 ALOGE("ICMP6_NA not found %d", it.get_type());\r
1371 return NL_SKIP;\r
1372 }\r
1373\r
1374 mGetWakeStats->rx_wake_pkt_classification_info .icmp6_na = it.get_u32();\r
1375 it.next();\r
1376\r
1377 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_NS) {\r
1378 ALOGE("ICMP6_NS not found %d", it.get_type());\r
1379 return NL_SKIP;\r
1380 }\r
1381\r
1382 mGetWakeStats->rx_wake_pkt_classification_info .icmp6_ns = it.get_u32();\r
1383 it.next();\r
1384\r
1385 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP4_RX_MULTICAST_CNT) {\r
1386 ALOGE("ICMP4_RX_MULTICAST_CNT not found %d", it.get_type());\r
1387 return NL_SKIP;\r
1388 }\r
1389\r
1390 mGetWakeStats->rx_multicast_wake_pkt_info.ipv4_rx_multicast_addr_cnt = it.get_u32();\r
1391 it.next();\r
1392\r
1393 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_RX_MULTICAST_CNT) {\r
1394 ALOGE("ICMP6_RX_MULTICAST_CNT not found %d", it.get_type());\r
1395 return NL_SKIP;\r
1396 }\r
1397\r
1398 mGetWakeStats->rx_multicast_wake_pkt_info.ipv6_rx_multicast_addr_cnt = it.get_u32();\r
1399 it.next();\r
1400\r
1401 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_OTHER_RX_MULTICAST_CNT) {\r
1402 ALOGE("OTHER_RX_MULTICAST_CNT not found %d", it.get_type());\r
1403 return NL_SKIP;\r
1404 }\r
1405\r
1406 mGetWakeStats->rx_multicast_wake_pkt_info.other_rx_multicast_addr_cnt = it.get_u32();\r
1407\r
1408 return NL_OK;\r
1409 }\r
1410\r
1411 int handleEvent(WifiEvent& event) {\r
1412 /* NO events to handle here! */\r
1413 return NL_SKIP;\r
1414 }\r
1415};\r
1416\r
1417 /* Function to get wake lock stats */\r
1418wifi_error wifi_get_wake_reason_stats(wifi_interface_handle iface,\r
1419 WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt)\r
1420{\r
1421 if(wifi_wake_reason_cnt) {\r
1422 WifiLoggerCommand *cmd = new WifiLoggerCommand(iface,wifi_wake_reason_cnt);\r
1423 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);\r
1424 wifi_error result = (wifi_error)cmd->start();\r
1425 cmd->releaseRef();\r
1426 return result;\r
1427 } else {\r
1428 ALOGE("Reason cnt NULL");\r
1429 return WIFI_ERROR_INVALID_ARGS;\r
1430 }\r
1431}\r
1432\r