[APR-2053]wlbt: NAN R2 integration fxes
[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
73e453d8 30/* using namespace android; */\r
cdc775c7
HG
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
cdc775c7 383\r
8094868d 384 ALOGD("len = %d, expected len = %lu", reply.get_vendor_data_len(), (unsigned long)sizeof(unsigned int));\r
cdc775c7
HG
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
402wifi_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
418wifi_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
434wifi_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
443wifi_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
460wifi_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
476wifi_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
492class SetLogHandler : public WifiCommand\r
493{\r
494 wifi_ring_buffer_data_handler mHandler;\r
495\r
496public:\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
575wifi_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
597wifi_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
617class 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
624public:\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
cdc775c7
HG
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
757wifi_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
779wifi_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
799class PacketFateCommand: public WifiCommand\r
800{\r
49d0342d 801 void *mReportBufs = NULL;\r
802 size_t mNoReqFates = 0;\r
803 size_t *mNoProvidedFates = NULL;\r
cdc775c7
HG
804 PktFateReqType mReqType;\r
805\r
806public:\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
8094868d 945 ALOGI("No: of pkt fates provided is %zu\n", *mNoProvidedFates);\r
cdc775c7
HG
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
961wifi_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
970wifi_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
b562d5aa 979 memset(tx_report_bufs, 0, (n_requested_fates * sizeof(wifi_tx_report)));\r
cdc775c7
HG
980 return result;\r
981}\r
982\r
983wifi_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
b562d5aa 992 memset(rx_report_bufs, 0, (n_requested_fates * sizeof(wifi_rx_report)));\r
cdc775c7
HG
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
0f3dba80 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
0f3dba80
MG
1007 {\r
1008 memset(&mcallback, 0, sizeof(wifi_driver_memory_dump_callbacks));\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
0f3dba80
MG
1014 memset(&mHandler, 0, sizeof(wifi_firmware_memory_dump_handler));\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
45011ff7 1127 break;\r
cdc775c7
HG
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
45011ff7
SP
1176 break;\r
1177 case GET_FW_VER:\r
8094868d
TK
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
cdc775c7
HG
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
1198wifi_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
1208wifi_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
1217class WifiLoggerCommand: public WifiCommand\r
1218{\r
1219 WLAN_DRIVER_WAKE_REASON_CNT *mGetWakeStats;\r
1220\r
1221public:\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
1430wifi_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