1/* Copyright (c) 2015, 2018 The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions
5 * are met:
6 *  * Redistributions of source code must retain the above copyright
7 *    notice, this list of conditions and the following disclaimer.
8 *  * Redistributions in binary form must reproduce the above
9 *    copyright notice, this list of conditions and the following
10 *    disclaimer in the documentation and/or other materials provided
11 *    with the distribution.
12 *  * Neither the name of The Linux Foundation nor the names of its
13 *    contributors may be used to endorse or promote products derived
14 *    from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/* Suppress -Waddress-of-packed-member for new toolchain update.
30 * Bug: http://b/33566695
31 */
32#if __clang_major__ >= 4
33#pragma clang diagnostic ignored "-Waddress-of-packed-member"
34#endif
35
36#include <netlink/genl/genl.h>
37#include <netlink/genl/family.h>
38#include <netlink/genl/ctrl.h>
39#include <linux/rtnetlink.h>
40#include <netinet/in.h>
41#include <cld80211_lib.h>
42#include "wifiloggercmd.h"
43#include "wifilogger_event_defs.h"
44#include "wifilogger_diag.h"
45#include "wifilogger_vendor_tag_defs.h"
46#include "pkt_stats.h"
47
48static uint32_t get_le32(const uint8_t *pos)
49{
50    return pos[0] | (pos[1] << 8) | (pos[2] << 16) | (pos[3] << 24);
51}
52
53#define MAX_CONNECTIVITY_EVENTS 18 // should match the value in wifi_logger.h
54static event_remap_t events[MAX_CONNECTIVITY_EVENTS] = {
55    {WLAN_PE_DIAG_ASSOC_REQ_EVENT, WIFI_EVENT_ASSOCIATION_REQUESTED},
56    {WLAN_PE_DIAG_AUTH_COMP_EVENT, WIFI_EVENT_AUTH_COMPLETE},
57    {WLAN_PE_DIAG_CONNECTED, WIFI_EVENT_ASSOC_COMPLETE},
58    {WLAN_PE_DIAG_AUTH_START_EVENT, WIFI_EVENT_FW_AUTH_STARTED},
59    {WLAN_PE_DIAG_ASSOC_START_EVENT, WIFI_EVENT_FW_ASSOC_STARTED},
60    {WLAN_PE_DIAG_REASSOC_START_EVENT, WIFI_EVENT_FW_RE_ASSOC_STARTED},
61    {WLAN_PE_DIAG_SCAN_REQ_EVENT, WIFI_EVENT_DRIVER_SCAN_REQUESTED},
62    {WLAN_PE_DIAG_SCAN_RES_FOUND_EVENT, WIFI_EVENT_DRIVER_SCAN_RESULT_FOUND},
63    {WLAN_PE_DIAG_SCAN_COMP_EVENT, WIFI_EVENT_DRIVER_SCAN_COMPLETE},
64    {WLAN_PE_DIAG_DISASSOC_REQ_EVENT, WIFI_EVENT_DISASSOCIATION_REQUESTED},
65    {WLAN_PE_DIAG_ASSOC_REQ_EVENT, WIFI_EVENT_RE_ASSOCIATION_REQUESTED},
66    {WLAN_PE_DIAG_ROAM_AUTH_START_EVENT, WIFI_EVENT_ROAM_AUTH_STARTED},
67    {WLAN_PE_DIAG_PRE_AUTH_RSP_EVENT, WIFI_EVENT_ROAM_AUTH_COMPLETE},
68    {WLAN_PE_DIAG_ROAM_ASSOC_START_EVENT, WIFI_EVENT_ROAM_ASSOC_STARTED},
69    {WLAN_PE_DIAG_ROAM_ASSOC_COMP_EVENT, WIFI_EVENT_ROAM_ASSOC_COMPLETE},
70    {WLAN_PE_DIAG_SWITCH_CHL_REQ_EVENT, WIFI_EVENT_CHANNEL_SWITCH_ANOUNCEMENT},
71    {WLAN_PE_DIAG_ASSOC_TIMEOUT, WIFI_EVENT_ASSOC_TIMEOUT},
72    {WLAN_PE_DIAG_AUTH_TIMEOUT, WIFI_EVENT_AUTH_TIMEOUT},
73};
74
75tlv_log* addLoggerTlv(u16 type, u16 length, u8* value, tlv_log *pOutTlv)
76{
77
78   pOutTlv->tag = type;
79   pOutTlv->length = length;
80   memcpy(&pOutTlv->value[0], value, length);
81
82   return((tlv_log *)((u8 *)pOutTlv + sizeof(tlv_log) + length));
83}
84
85int add_reason_code_tag(tlv_log **tlvs, u16 reason_code)
86{
87    *tlvs = addLoggerTlv(WIFI_TAG_REASON_CODE, sizeof(u16),
88                        (u8 *)&reason_code, *tlvs);
89    return (sizeof(tlv_log) + sizeof(u16));
90}
91
92int add_status_tag(tlv_log **tlvs, int status)
93{
94    *tlvs = addLoggerTlv(WIFI_TAG_STATUS, sizeof(int),
95                        (u8 *)&status, *tlvs);
96    return (sizeof(tlv_log) + sizeof(int));
97}
98
99static wifi_error update_connectivity_ring_buf(hal_info *info,
100                                               wifi_ring_buffer_entry *rbe,
101                                               u32 size)
102{
103    struct timeval time;
104    u32 total_length = size + sizeof(wifi_ring_buffer_entry);
105
106    rbe->entry_size = size;
107    rbe->flags = RING_BUFFER_ENTRY_FLAGS_HAS_BINARY |
108                              RING_BUFFER_ENTRY_FLAGS_HAS_TIMESTAMP;
109    rbe->type = ENTRY_TYPE_CONNECT_EVENT;
110    gettimeofday(&time,NULL);
111    rbe->timestamp = time.tv_usec + time.tv_sec * 1000 * 1000;
112
113    /* Write if verbose level and handler are set */
114    if (info->rb_infos[CONNECTIVITY_EVENTS_RB_ID].verbose_level >= 1 &&
115        info->on_ring_buffer_data) {
116        return ring_buffer_write(&info->rb_infos[CONNECTIVITY_EVENTS_RB_ID],
117                      (u8*)rbe, total_length, 1, total_length);
118    }
119
120    return WIFI_SUCCESS;
121}
122
123#define SCAN_CAP_ENTRY_SIZE 1024
124static wifi_error process_log_extscan_capabilities(hal_info *info,
125                                                   u8* buf, int length)
126{
127    wifi_ring_buffer_driver_connectivity_event *pConnectEvent;
128    wifi_ring_buffer_entry *pRingBufferEntry;
129    wlan_ext_scan_capabilities_payload_type *pScanCapabilities;
130    wifi_gscan_capabilities gscan_cap;
131    gscan_capabilities_vendor_data_t cap_vendor_data;
132    tlv_log *pTlv;
133    int tot_len = sizeof(wifi_ring_buffer_driver_connectivity_event);
134    u8 out_buf[SCAN_CAP_ENTRY_SIZE];
135    wifi_error status;
136
137    pRingBufferEntry = (wifi_ring_buffer_entry *)&out_buf[0];
138    memset(pRingBufferEntry, 0, SCAN_CAP_ENTRY_SIZE);
139    memset(&cap_vendor_data, 0, sizeof(gscan_capabilities_vendor_data_t));
140    pConnectEvent = (wifi_ring_buffer_driver_connectivity_event *)
141                     (pRingBufferEntry + 1);
142
143    pConnectEvent->event = WIFI_EVENT_G_SCAN_CAPABILITIES;
144    pTlv = &pConnectEvent->tlvs[0];
145
146    pScanCapabilities = (wlan_ext_scan_capabilities_payload_type *)buf;
147    pTlv = addLoggerTlv(WIFI_TAG_REQUEST_ID,
148                        sizeof(pScanCapabilities->request_id),
149                        (u8 *)&pScanCapabilities->request_id, pTlv);
150    tot_len += sizeof(tlv_log) + sizeof(pScanCapabilities->request_id);
151
152    gscan_cap.max_scan_cache_size =
153        pScanCapabilities->extscan_cache_capabilities.scan_cache_entry_size;
154    gscan_cap.max_scan_buckets =
155        pScanCapabilities->extscan_cache_capabilities.max_buckets;
156    gscan_cap.max_ap_cache_per_scan =
157        pScanCapabilities->extscan_cache_capabilities.max_bssid_per_scan;
158    gscan_cap.max_rssi_sample_size = FEATURE_NOT_SUPPORTED;
159    gscan_cap.max_scan_reporting_threshold =
160        pScanCapabilities->extscan_cache_capabilities.max_table_usage_threshold;
161    gscan_cap.max_hotlist_bssids =
162        pScanCapabilities->extscan_hotlist_monitor_capabilities.max_hotlist_entries;
163    gscan_cap.max_hotlist_ssids =
164        pScanCapabilities->extscan_capabilities.num_extscan_hotlist_ssid;
165    gscan_cap.max_significant_wifi_change_aps = FEATURE_NOT_SUPPORTED;
166    gscan_cap.max_bssid_history_entries = FEATURE_NOT_SUPPORTED;
167    gscan_cap.max_number_epno_networks =
168        pScanCapabilities->extscan_capabilities.num_epno_networks;
169    gscan_cap.max_number_epno_networks_by_ssid =
170        pScanCapabilities->extscan_capabilities.num_epno_networks;
171    gscan_cap.max_number_of_white_listed_ssid =
172        pScanCapabilities->extscan_capabilities.num_roam_ssid_whitelist;
173
174    pTlv = addLoggerTlv(WIFI_TAG_GSCAN_CAPABILITIES,
175                        sizeof(wifi_gscan_capabilities),
176                        (u8 *)&gscan_cap, pTlv);
177    tot_len += sizeof(tlv_log) + sizeof(wifi_gscan_capabilities);
178
179    cap_vendor_data.hotlist_mon_table_id =
180        pScanCapabilities->extscan_hotlist_monitor_capabilities.table_id;
181    cap_vendor_data.wlan_hotlist_entry_size =
182        pScanCapabilities->extscan_hotlist_monitor_capabilities.wlan_hotlist_entry_size;
183    cap_vendor_data.cache_cap_table_id =
184        pScanCapabilities->extscan_cache_capabilities.table_id;
185    cap_vendor_data.requestor_id =
186        pScanCapabilities->extscan_capabilities.requestor_id;
187    cap_vendor_data.vdev_id =
188        pScanCapabilities->extscan_capabilities.vdev_id;
189    cap_vendor_data.num_extscan_cache_tables =
190        pScanCapabilities->extscan_capabilities.num_extscan_cache_tables;
191    cap_vendor_data.num_wlan_change_monitor_tables =
192        pScanCapabilities->extscan_capabilities.num_wlan_change_monitor_tables;
193    cap_vendor_data.num_hotlist_monitor_tables =
194        pScanCapabilities->extscan_capabilities.num_hotlist_monitor_tables;
195    cap_vendor_data.rtt_one_sided_supported =
196        pScanCapabilities->extscan_capabilities.rtt_one_sided_supported;
197    cap_vendor_data.rtt_11v_supported =
198        pScanCapabilities->extscan_capabilities.rtt_11v_supported;
199    cap_vendor_data.rtt_ftm_supported =
200        pScanCapabilities->extscan_capabilities.rtt_ftm_supported;
201    cap_vendor_data.num_extscan_cache_capabilities =
202        pScanCapabilities->extscan_capabilities.num_extscan_cache_capabilities;
203    cap_vendor_data.num_extscan_wlan_change_capabilities =
204        pScanCapabilities->extscan_capabilities.num_extscan_wlan_change_capabilities;
205    cap_vendor_data.num_extscan_hotlist_capabilities =
206        pScanCapabilities->extscan_capabilities.num_extscan_hotlist_capabilities;
207    cap_vendor_data.num_roam_bssid_blacklist =
208        pScanCapabilities->extscan_capabilities.num_roam_bssid_blacklist;
209    cap_vendor_data.num_roam_bssid_preferred_list =
210        pScanCapabilities->extscan_capabilities.num_roam_bssid_preferred_list;
211
212    pTlv = addLoggerTlv(WIFI_TAG_VENDOR_SPECIFIC,
213                        sizeof(gscan_capabilities_vendor_data_t),
214                        (u8 *)&cap_vendor_data, pTlv);
215    tot_len += sizeof(tlv_log) + sizeof(gscan_capabilities_vendor_data_t);
216
217    status = update_connectivity_ring_buf(info, pRingBufferEntry, tot_len);
218    if (status != WIFI_SUCCESS) {
219        ALOGE("Failed to write ext scan capabilities event into ring buffer");
220    }
221    return status;
222}
223
224static wifi_error process_bt_coex_scan_event(hal_info *info,
225                                             u32 id, u8* buf, int length)
226{
227    wifi_ring_buffer_driver_connectivity_event *pConnectEvent;
228    wifi_ring_buffer_entry *pRingBufferEntry;
229    tlv_log *pTlv;
230    int tot_len = sizeof(wifi_ring_buffer_driver_connectivity_event);
231    u8 out_buf[RING_BUF_ENTRY_SIZE];
232    wifi_error status;
233
234    pRingBufferEntry = (wifi_ring_buffer_entry *)&out_buf[0];
235    memset(pRingBufferEntry, 0, RING_BUF_ENTRY_SIZE);
236    pConnectEvent = (wifi_ring_buffer_driver_connectivity_event *)
237                     (pRingBufferEntry + 1);
238    pTlv = &pConnectEvent->tlvs[0];
239
240    if (id == EVENT_WLAN_BT_COEX_BT_SCAN_START) {
241        wlan_bt_coex_bt_scan_start_payload_type *pBtScanStart;
242        bt_coex_bt_scan_start_vendor_data_t btScanStartVenData;
243
244        pConnectEvent->event = WIFI_EVENT_BT_COEX_BT_SCAN_START;
245
246        pBtScanStart = (wlan_bt_coex_bt_scan_start_payload_type *)buf;
247        btScanStartVenData.scan_type = pBtScanStart->scan_type;
248        btScanStartVenData.scan_bitmap = pBtScanStart->scan_bitmap;
249
250        pTlv = addLoggerTlv(WIFI_TAG_VENDOR_SPECIFIC,
251                            sizeof(bt_coex_bt_scan_start_vendor_data_t),
252                            (u8 *)&btScanStartVenData, pTlv);
253        tot_len += sizeof(tlv_log) +
254                   sizeof(bt_coex_bt_scan_start_vendor_data_t);
255    } else if(id == EVENT_WLAN_BT_COEX_BT_SCAN_STOP) {
256        wlan_bt_coex_bt_scan_stop_payload_type *pBtScanStop;
257        bt_coex_bt_scan_stop_vendor_data_t btScanStopVenData;
258
259        pConnectEvent->event = WIFI_EVENT_BT_COEX_BT_SCAN_STOP;
260
261        pBtScanStop = (wlan_bt_coex_bt_scan_stop_payload_type *)buf;
262        btScanStopVenData.scan_type = pBtScanStop->scan_type;
263        btScanStopVenData.scan_bitmap = pBtScanStop->scan_bitmap;
264
265        pTlv = addLoggerTlv(WIFI_TAG_VENDOR_SPECIFIC,
266                            sizeof(bt_coex_bt_scan_stop_vendor_data_t),
267                            (u8 *)&btScanStopVenData, pTlv);
268        tot_len += sizeof(tlv_log) + sizeof(bt_coex_bt_scan_stop_vendor_data_t);
269    }
270    status = update_connectivity_ring_buf(info, pRingBufferEntry, tot_len);
271    if (status != WIFI_SUCCESS) {
272        ALOGE("Failed to write bt_coex_scan event into ring buffer");
273    }
274
275    return status;
276}
277
278static wifi_error process_bt_coex_event(hal_info *info, u32 id,
279                                        u8* buf, int length)
280{
281    wifi_ring_buffer_driver_connectivity_event *pConnectEvent;
282    wifi_ring_buffer_entry *pRingBufferEntry;
283    tlv_log *pTlv;
284    int tot_len = sizeof(wifi_ring_buffer_driver_connectivity_event);
285    u8 out_buf[RING_BUF_ENTRY_SIZE];
286    u8 link_id, link_state, link_role, link_type = 0, Rsco = 0;
287    u16 Tsco = 0;
288    wifi_error status;
289    bt_coex_hid_vendor_data_t btCoexHidVenData;
290
291    pRingBufferEntry = (wifi_ring_buffer_entry *)&out_buf[0];
292    memset(pRingBufferEntry, 0, RING_BUF_ENTRY_SIZE);
293    pConnectEvent = (wifi_ring_buffer_driver_connectivity_event *)
294                     (pRingBufferEntry + 1);
295
296    switch (id) {
297        case EVENT_WLAN_BT_COEX_BT_SCO_START:
298        {
299            wlan_bt_coex_bt_sco_start_payload_type *pBtCoexStartPL;
300            pBtCoexStartPL = (wlan_bt_coex_bt_sco_start_payload_type *)buf;
301
302            link_id = pBtCoexStartPL->link_id;
303            link_state = pBtCoexStartPL->link_state;
304            link_role = pBtCoexStartPL->link_role;
305            link_type = pBtCoexStartPL->link_type;
306            Tsco = pBtCoexStartPL->Tsco;
307            Rsco = pBtCoexStartPL->Rsco;
308
309            pConnectEvent->event = WIFI_EVENT_BT_COEX_BT_SCO_START;
310        }
311        break;
312        case EVENT_WLAN_BT_COEX_BT_SCO_STOP:
313        {
314            wlan_bt_coex_bt_sco_stop_payload_type *pBtCoexStopPL;
315            pBtCoexStopPL = (wlan_bt_coex_bt_sco_stop_payload_type *)buf;
316
317            link_id = pBtCoexStopPL->link_id;
318            link_state = pBtCoexStopPL->link_state;
319            link_role = pBtCoexStopPL->link_role;
320            link_type = pBtCoexStopPL->link_type;
321            Tsco = pBtCoexStopPL->Tsco;
322            Rsco = pBtCoexStopPL->Rsco;
323
324            pConnectEvent->event = WIFI_EVENT_BT_COEX_BT_SCO_STOP;
325        }
326        break;
327        case EVENT_WLAN_BT_COEX_BT_HID_START:
328        {
329            wlan_bt_coex_bt_hid_start_payload_type *pBtCoexHidStartPL;
330            pBtCoexHidStartPL = (wlan_bt_coex_bt_hid_start_payload_type *)buf;
331
332            link_id = pBtCoexHidStartPL->link_id;
333            link_state = pBtCoexHidStartPL->link_state;
334            link_role = pBtCoexHidStartPL->link_role;
335            btCoexHidVenData.Tsniff = pBtCoexHidStartPL->Tsniff;
336            btCoexHidVenData.attempts = pBtCoexHidStartPL->attempts;
337
338            pConnectEvent->event = WIFI_EVENT_BT_COEX_BT_HID_START;
339        }
340        break;
341        case EVENT_WLAN_BT_COEX_BT_HID_STOP:
342        {
343            wlan_bt_coex_bt_hid_stop_payload_type *pBtCoexHidStopPL;
344            pBtCoexHidStopPL = (wlan_bt_coex_bt_hid_stop_payload_type *)buf;
345
346            link_id = pBtCoexHidStopPL->link_id;
347            link_state = pBtCoexHidStopPL->link_state;
348            link_role = pBtCoexHidStopPL->link_role;
349            btCoexHidVenData.Tsniff = pBtCoexHidStopPL->Tsniff;
350            btCoexHidVenData.attempts = pBtCoexHidStopPL->attempts;
351
352            pConnectEvent->event = WIFI_EVENT_BT_COEX_BT_HID_STOP;
353        }
354        break;
355        default:
356            return WIFI_SUCCESS;
357    }
358
359    pTlv = &pConnectEvent->tlvs[0];
360    pTlv = addLoggerTlv(WIFI_TAG_LINK_ID, sizeof(link_id), &link_id, pTlv);
361    tot_len += sizeof(tlv_log) + sizeof(link_id);
362
363    pTlv = addLoggerTlv(WIFI_TAG_LINK_ROLE, sizeof(link_role),
364                        &link_role, pTlv);
365    tot_len += sizeof(tlv_log) + sizeof(link_role);
366
367    pTlv = addLoggerTlv(WIFI_TAG_LINK_STATE, sizeof(link_state),
368                        &link_state, pTlv);
369    tot_len += sizeof(tlv_log) + sizeof(link_state);
370
371    if ((pConnectEvent->event == EVENT_WLAN_BT_COEX_BT_SCO_START) ||
372        (pConnectEvent->event == EVENT_WLAN_BT_COEX_BT_SCO_STOP)) {
373        pTlv = addLoggerTlv(WIFI_TAG_LINK_TYPE, sizeof(link_type),
374                            &link_type, pTlv);
375        tot_len += sizeof(tlv_log) + sizeof(link_type);
376
377        pTlv = addLoggerTlv(WIFI_TAG_TSCO, sizeof(Tsco), (u8 *)&Tsco, pTlv);
378        tot_len += sizeof(tlv_log) + sizeof(Tsco);
379
380        pTlv = addLoggerTlv(WIFI_TAG_RSCO, sizeof(Rsco), &Rsco, pTlv);
381        tot_len += sizeof(tlv_log) + sizeof(Rsco);
382    } else if ((pConnectEvent->event == EVENT_WLAN_BT_COEX_BT_HID_START) ||
383               (pConnectEvent->event == EVENT_WLAN_BT_COEX_BT_HID_STOP)) {
384        pTlv = addLoggerTlv(WIFI_TAG_VENDOR_SPECIFIC,
385                            sizeof(bt_coex_hid_vendor_data_t),
386                            (u8 *)&btCoexHidVenData, pTlv);
387        tot_len += sizeof(tlv_log) + sizeof(bt_coex_hid_vendor_data_t);
388    }
389
390    status = update_connectivity_ring_buf(info, pRingBufferEntry, tot_len);
391    if (status != WIFI_SUCCESS) {
392        ALOGE("Failed to write bt_coex_event into ring buffer");
393    }
394
395    return status;
396}
397
398static wifi_error process_extscan_event(hal_info *info, u32 id,
399                                        u8* buf, int length)
400{
401    wifi_ring_buffer_driver_connectivity_event *pConnectEvent;
402    wifi_ring_buffer_entry *pRingBufferEntry;
403    tlv_log *pTlv;
404    int tot_len = sizeof(wifi_ring_buffer_driver_connectivity_event);
405    u8 out_buf[RING_BUF_ENTRY_SIZE];
406    wifi_error status;
407
408    pRingBufferEntry = (wifi_ring_buffer_entry *)&out_buf[0];
409    memset(pRingBufferEntry, 0, RING_BUF_ENTRY_SIZE);
410    pConnectEvent = (wifi_ring_buffer_driver_connectivity_event *)
411                     (pRingBufferEntry + 1);
412    pTlv = &pConnectEvent->tlvs[0];
413
414    switch (id) {
415    case EVENT_WLAN_EXTSCAN_CYCLE_STARTED:
416        {
417            ext_scan_cycle_vendor_data_t extScanCycleVenData;
418            wlan_ext_scan_cycle_started_payload_type *pExtScanCycleStarted;
419            pConnectEvent->event = WIFI_EVENT_G_SCAN_CYCLE_STARTED;
420            pExtScanCycleStarted =
421                           (wlan_ext_scan_cycle_started_payload_type *)buf;
422            pTlv = addLoggerTlv(WIFI_TAG_SCAN_ID, sizeof(u32),
423                            (u8 *)&pExtScanCycleStarted->scan_id, pTlv);
424            tot_len += sizeof(tlv_log) + sizeof(u32);
425
426            extScanCycleVenData.timer_tick = pExtScanCycleStarted->timer_tick;
427            extScanCycleVenData.scheduled_bucket_mask =
428                                    pExtScanCycleStarted->scheduled_bucket_mask;
429            extScanCycleVenData.scan_cycle_count =
430                                         pExtScanCycleStarted->scan_cycle_count;
431
432            pTlv = addLoggerTlv(WIFI_TAG_VENDOR_SPECIFIC,
433                                sizeof(ext_scan_cycle_vendor_data_t),
434                                (u8 *)&extScanCycleVenData, pTlv);
435            tot_len += sizeof(tlv_log) + sizeof(ext_scan_cycle_vendor_data_t);
436        }
437        break;
438    case EVENT_WLAN_EXTSCAN_CYCLE_COMPLETED:
439        {
440            ext_scan_cycle_vendor_data_t extScanCycleVenData;
441            wlan_ext_scan_cycle_completed_payload_type *pExtScanCycleCompleted;
442            pConnectEvent->event = WIFI_EVENT_G_SCAN_CYCLE_COMPLETED;
443            pExtScanCycleCompleted =
444            (wlan_ext_scan_cycle_completed_payload_type *)buf;
445            pTlv = addLoggerTlv(WIFI_TAG_SCAN_ID, sizeof(u32),
446                            (u8 *)&pExtScanCycleCompleted->scan_id, pTlv);
447            tot_len += sizeof(tlv_log) + sizeof(u32);
448
449            extScanCycleVenData.timer_tick = pExtScanCycleCompleted->timer_tick;
450            extScanCycleVenData.scheduled_bucket_mask =
451                                  pExtScanCycleCompleted->scheduled_bucket_mask;
452            extScanCycleVenData.scan_cycle_count =
453                                       pExtScanCycleCompleted->scan_cycle_count;
454
455            pTlv = addLoggerTlv(WIFI_TAG_VENDOR_SPECIFIC,
456                                sizeof(ext_scan_cycle_vendor_data_t),
457                                (u8 *)&extScanCycleVenData, pTlv);
458            tot_len += sizeof(tlv_log) + sizeof(ext_scan_cycle_vendor_data_t);
459        }
460        break;
461    case EVENT_WLAN_EXTSCAN_BUCKET_STARTED:
462        {
463            wlan_ext_scan_bucket_started_payload_type *pExtScanBucketStarted;
464            u32 bucket_id;
465            pConnectEvent->event = WIFI_EVENT_G_SCAN_BUCKET_STARTED;
466            pExtScanBucketStarted =
467                            (wlan_ext_scan_bucket_started_payload_type *)buf;
468            bucket_id = (u32)pExtScanBucketStarted->bucket_id;
469            pTlv = addLoggerTlv(WIFI_TAG_BUCKET_ID, sizeof(u32),
470                                (u8 *)&bucket_id, pTlv);
471            tot_len += sizeof(tlv_log) + sizeof(u32);
472        }
473        break;
474    case EVENT_WLAN_EXTSCAN_BUCKET_COMPLETED:
475        {
476            wlan_ext_scan_bucket_completed_payload_type *pExtScanBucketCmpleted;
477            u32 bucket_id;
478            pConnectEvent->event = WIFI_EVENT_G_SCAN_BUCKET_COMPLETED;
479            pExtScanBucketCmpleted =
480                            (wlan_ext_scan_bucket_completed_payload_type *)buf;
481            bucket_id = (u32)pExtScanBucketCmpleted->bucket_id;
482            pTlv = addLoggerTlv(WIFI_TAG_BUCKET_ID, sizeof(u32),
483                                (u8 *)&bucket_id, pTlv);
484            tot_len += sizeof(tlv_log) + sizeof(u32);
485        }
486        break;
487    case EVENT_WLAN_EXTSCAN_FEATURE_STOP:
488        {
489            wlan_ext_scan_feature_stop_payload_type *pExtScanStop;
490            pConnectEvent->event = WIFI_EVENT_G_SCAN_STOP;
491            pExtScanStop = (wlan_ext_scan_feature_stop_payload_type *)buf;
492            pTlv = addLoggerTlv(WIFI_TAG_REQUEST_ID,
493                                sizeof(pExtScanStop->request_id),
494                                (u8 *)&pExtScanStop->request_id, pTlv);
495            tot_len += sizeof(tlv_log) +
496                       sizeof(wlan_ext_scan_feature_stop_payload_type);
497        }
498        break;
499    case EVENT_WLAN_EXTSCAN_RESULTS_AVAILABLE:
500        {
501            wlan_ext_scan_results_available_payload_type *pExtScanResultsAvail;
502            ext_scan_results_available_vendor_data_t extScanResultsAvailVenData;
503            u32 request_id;
504            pConnectEvent->event = WIFI_EVENT_G_SCAN_RESULTS_AVAILABLE;
505            pExtScanResultsAvail =
506                          (wlan_ext_scan_results_available_payload_type *)buf;
507            request_id = pExtScanResultsAvail->request_id;
508            pTlv = addLoggerTlv(WIFI_TAG_REQUEST_ID, sizeof(u32),
509                          (u8 *)&request_id, pTlv);
510            tot_len += sizeof(tlv_log) + sizeof(u32);
511
512            extScanResultsAvailVenData.table_type =
513                                               pExtScanResultsAvail->table_type;
514            extScanResultsAvailVenData.entries_in_use =
515                                           pExtScanResultsAvail->entries_in_use;
516            extScanResultsAvailVenData.maximum_entries =
517                                          pExtScanResultsAvail->maximum_entries;
518            extScanResultsAvailVenData.scan_count_after_getResults =
519                              pExtScanResultsAvail->scan_count_after_getResults;
520            extScanResultsAvailVenData.threshold_num_scans =
521                                      pExtScanResultsAvail->threshold_num_scans;
522
523            pTlv = addLoggerTlv(WIFI_TAG_VENDOR_SPECIFIC,
524                              sizeof(ext_scan_results_available_vendor_data_t),
525                                (u8 *)&extScanResultsAvailVenData, pTlv);
526            tot_len += sizeof(tlv_log) +
527                       sizeof(ext_scan_results_available_vendor_data_t);
528        }
529        break;
530    }
531
532    status = update_connectivity_ring_buf(info, pRingBufferEntry, tot_len);
533    if (status != WIFI_SUCCESS) {
534        ALOGE("Failed to write ext_scan event into ring buffer");
535    }
536
537    return status;
538}
539
540static wifi_error process_addba_success_event(hal_info *info,
541                                      u8* buf, int length)
542{
543    wifi_ring_buffer_driver_connectivity_event *pConnectEvent;
544    wifi_ring_buffer_entry *pRingBufferEntry;
545    tlv_log *pTlv;
546    int tot_len = sizeof(wifi_ring_buffer_driver_connectivity_event);
547    u8 out_buf[RING_BUF_ENTRY_SIZE];
548    wlan_add_block_ack_success_payload_type *pAddBASuccess;
549    addba_success_vendor_data_t addBASuccessVenData;
550    wifi_error status;
551
552    pRingBufferEntry = (wifi_ring_buffer_entry *)&out_buf[0];
553    memset(pRingBufferEntry, 0, RING_BUF_ENTRY_SIZE);
554    pConnectEvent = (wifi_ring_buffer_driver_connectivity_event *)
555                     (pRingBufferEntry + 1);
556    pAddBASuccess = (wlan_add_block_ack_success_payload_type *)buf;
557
558    addBASuccessVenData.ucBaTid = pAddBASuccess->ucBaTid;
559    addBASuccessVenData.ucBaBufferSize = pAddBASuccess->ucBaBufferSize;
560    addBASuccessVenData.ucBaSSN = pAddBASuccess->ucBaSSN;
561    addBASuccessVenData.fInitiator = pAddBASuccess->fInitiator;
562
563    pConnectEvent->event = WIFI_EVENT_BLOCK_ACK_NEGOTIATION_COMPLETE;
564    pTlv = &pConnectEvent->tlvs[0];
565    pTlv = addLoggerTlv(WIFI_TAG_ADDR, sizeof(pAddBASuccess->ucBaPeerMac),
566                        (u8 *)pAddBASuccess->ucBaPeerMac, pTlv);
567    tot_len += sizeof(tlv_log) + sizeof(pAddBASuccess->ucBaPeerMac);
568
569    tot_len += add_status_tag(&pTlv, (int)ADDBA_SUCCESS);
570
571    pTlv = addLoggerTlv(WIFI_TAG_VENDOR_SPECIFIC,
572                        sizeof(addba_success_vendor_data_t),
573                        (u8 *)&addBASuccessVenData, pTlv);
574    tot_len += sizeof(tlv_log) + sizeof(addba_success_vendor_data_t);
575
576    status = update_connectivity_ring_buf(info, pRingBufferEntry, tot_len);
577    if (status != WIFI_SUCCESS) {
578        ALOGE("Failed to write addba event into ring buffer");
579    }
580
581    return status;
582}
583
584static wifi_error process_addba_failed_event(hal_info *info,
585                                      u8* buf, int length)
586{
587    wifi_ring_buffer_driver_connectivity_event *pConnectEvent;
588    wifi_ring_buffer_entry *pRingBufferEntry;
589    tlv_log *pTlv;
590    int tot_len = sizeof(wifi_ring_buffer_driver_connectivity_event);
591    u8 out_buf[RING_BUF_ENTRY_SIZE];
592    wlan_add_block_ack_failed_payload_type *pAddBAFailed;
593    addba_failed_vendor_data_t addBAFailedVenData;
594    wifi_error status;
595
596    pRingBufferEntry = (wifi_ring_buffer_entry *)&out_buf[0];
597    memset(pRingBufferEntry, 0, RING_BUF_ENTRY_SIZE);
598    pConnectEvent = (wifi_ring_buffer_driver_connectivity_event *)
599                     (pRingBufferEntry + 1);
600
601    pAddBAFailed = (wlan_add_block_ack_failed_payload_type *)buf;
602    addBAFailedVenData.ucBaTid = pAddBAFailed->ucBaTid;
603    addBAFailedVenData.fInitiator = pAddBAFailed->fInitiator;
604
605    pConnectEvent->event = WIFI_EVENT_BLOCK_ACK_NEGOTIATION_COMPLETE;
606    pTlv = &pConnectEvent->tlvs[0];
607    pTlv = addLoggerTlv(WIFI_TAG_ADDR, sizeof(pAddBAFailed->ucBaPeerMac),
608                        (u8 *)pAddBAFailed->ucBaPeerMac, pTlv);
609    tot_len += sizeof(tlv_log) + sizeof(pAddBAFailed->ucBaPeerMac);
610
611    tot_len += add_status_tag(&pTlv, (int)ADDBA_FAILURE);
612
613    tot_len += add_reason_code_tag(&pTlv, (u16)pAddBAFailed->ucReasonCode);
614
615    pTlv = addLoggerTlv(WIFI_TAG_VENDOR_SPECIFIC,
616                        sizeof(addba_failed_vendor_data_t),
617                        (u8 *)&addBAFailedVenData, pTlv);
618    tot_len += sizeof(tlv_log) + sizeof(addba_failed_vendor_data_t);
619
620    status = update_connectivity_ring_buf(info, pRingBufferEntry, tot_len);
621    if (status != WIFI_SUCCESS) {
622        ALOGE("Failed to write addba event into ring buffer");
623    }
624
625    return status;
626}
627
628static wifi_error process_roam_event(hal_info *info, u32 id,
629                                     u8* buf, int length)
630{
631    wifi_ring_buffer_driver_connectivity_event *pConnectEvent;
632    wifi_ring_buffer_entry *pRingBufferEntry;
633    tlv_log *pTlv;
634    int tot_len = sizeof(wifi_ring_buffer_driver_connectivity_event);
635    u8 out_buf[RING_BUF_ENTRY_SIZE];
636    wifi_error status;
637
638    pRingBufferEntry = (wifi_ring_buffer_entry *)&out_buf[0];
639    memset(pRingBufferEntry, 0, RING_BUF_ENTRY_SIZE);
640    pConnectEvent = (wifi_ring_buffer_driver_connectivity_event *)
641                     (pRingBufferEntry + 1);
642
643    switch (id)
644    {
645    case EVENT_WLAN_ROAM_SCAN_STARTED:
646        {
647            wlan_roam_scan_started_payload_type *pRoamScanStarted;
648            roam_scan_started_vendor_data_t roamScanStartedVenData;
649            pConnectEvent->event = WIFI_EVENT_ROAM_SCAN_STARTED;
650            pRoamScanStarted = (wlan_roam_scan_started_payload_type *)buf;
651            pTlv = &pConnectEvent->tlvs[0];
652            pTlv = addLoggerTlv(WIFI_TAG_SCAN_ID,
653                                sizeof(pRoamScanStarted->scan_id),
654                                (u8 *)&pRoamScanStarted->scan_id, pTlv);
655            tot_len += sizeof(tlv_log) + sizeof(pRoamScanStarted->scan_id);
656            roamScanStartedVenData.roam_scan_flags =
657                                              pRoamScanStarted->roam_scan_flags;
658            roamScanStartedVenData.cur_rssi = pRoamScanStarted->cur_rssi;
659            memcpy(roamScanStartedVenData.scan_params,
660                   pRoamScanStarted->scan_params,
661                   sizeof(roamScanStartedVenData.scan_params));
662            memcpy(roamScanStartedVenData.scan_channels,
663                   pRoamScanStarted->scan_channels,
664                   sizeof(roamScanStartedVenData.scan_channels));
665            pTlv = addLoggerTlv(WIFI_TAG_VENDOR_SPECIFIC,
666                                sizeof(roam_scan_started_vendor_data_t),
667                                (u8 *)&roamScanStartedVenData, pTlv);
668            tot_len += sizeof(tlv_log) +
669                       sizeof(roam_scan_started_vendor_data_t);
670        }
671        break;
672    case EVENT_WLAN_ROAM_SCAN_COMPLETE:
673        {
674            wlan_roam_scan_complete_payload_type *pRoamScanComplete;
675            roam_scan_complete_vendor_data_t roamScanCompleteVenData;
676            pConnectEvent->event = WIFI_EVENT_ROAM_SCAN_COMPLETE;
677            pRoamScanComplete = (wlan_roam_scan_complete_payload_type *)buf;
678            pTlv = &pConnectEvent->tlvs[0];
679
680            pTlv = addLoggerTlv(WIFI_TAG_SCAN_ID,
681                                sizeof(pRoamScanComplete->scan_id),
682                                (u8 *)&pRoamScanComplete->scan_id, pTlv);
683            tot_len += sizeof(tlv_log) + sizeof(pRoamScanComplete->scan_id);
684
685            roamScanCompleteVenData.reason = pRoamScanComplete->reason;
686            roamScanCompleteVenData.completion_flags =
687                                            pRoamScanComplete->completion_flags;
688            roamScanCompleteVenData.num_candidate =
689                                               pRoamScanComplete->num_candidate;
690            roamScanCompleteVenData.flags = pRoamScanComplete->flags;
691
692            pTlv = addLoggerTlv(WIFI_TAG_VENDOR_SPECIFIC,
693                                sizeof(roam_scan_complete_vendor_data_t),
694                                (u8 *)&roamScanCompleteVenData, pTlv);
695            tot_len += sizeof(tlv_log) +
696                       sizeof(roam_scan_complete_vendor_data_t);
697        }
698        break;
699    case EVENT_WLAN_ROAM_CANDIDATE_FOUND:
700        {
701            wlan_roam_candidate_found_payload_type *pRoamCandidateFound;
702            roam_candidate_found_vendor_data_t roamCandidateFoundVendata;
703            pConnectEvent->event = WIFI_EVENT_ROAM_CANDIDATE_FOUND;
704            pRoamCandidateFound = (wlan_roam_candidate_found_payload_type *)buf;
705            memset(&roamCandidateFoundVendata, 0,
706                   sizeof(roam_candidate_found_vendor_data_t));
707            pTlv = &pConnectEvent->tlvs[0];
708            pTlv = addLoggerTlv(WIFI_TAG_CHANNEL,
709                                sizeof(pRoamCandidateFound->channel),
710                                (u8 *)&pRoamCandidateFound->channel, pTlv);
711            tot_len += sizeof(tlv_log) + sizeof(pRoamCandidateFound->channel);
712
713            pTlv = addLoggerTlv(WIFI_TAG_RSSI,
714                                sizeof(pRoamCandidateFound->rssi),
715                                (u8 *)&pRoamCandidateFound->rssi, pTlv);
716            tot_len += sizeof(tlv_log) + sizeof(pRoamCandidateFound->rssi);
717
718            pTlv = addLoggerTlv(WIFI_TAG_BSSID,
719                                sizeof(pRoamCandidateFound->bssid),
720                                (u8 *)pRoamCandidateFound->bssid, pTlv);
721            tot_len += sizeof(tlv_log) + sizeof(pRoamCandidateFound->bssid);
722
723            pTlv = addLoggerTlv(WIFI_TAG_SSID,
724                                sizeof(pRoamCandidateFound->ssid),
725                                (u8 *)pRoamCandidateFound->ssid, pTlv);
726            tot_len += sizeof(tlv_log) + sizeof(pRoamCandidateFound->ssid);
727
728            roamCandidateFoundVendata.auth_mode =
729                                   pRoamCandidateFound->auth_mode;
730            roamCandidateFoundVendata.ucast_cipher =
731                                         pRoamCandidateFound->ucast_cipher;
732            roamCandidateFoundVendata.mcast_cipher =
733                                         pRoamCandidateFound->mcast_cipher;
734            pTlv = addLoggerTlv(WIFI_TAG_VENDOR_SPECIFIC,
735                                sizeof(roam_candidate_found_vendor_data_t),
736                                (u8 *)&roamCandidateFoundVendata, pTlv);
737            tot_len += sizeof(tlv_log) +
738                       sizeof(roam_candidate_found_vendor_data_t);
739        }
740        break;
741        case EVENT_WLAN_ROAM_SCAN_CONFIG:
742        {
743            wlan_roam_scan_config_payload_type *pRoamScanConfig;
744            roam_scan_config_vendor_data_t roamScanConfigVenData;
745
746            pConnectEvent->event = WIFI_EVENT_ROAM_SCAN_CONFIG;
747            pRoamScanConfig = (wlan_roam_scan_config_payload_type *)buf;
748
749            pTlv = &pConnectEvent->tlvs[0];
750
751            roamScanConfigVenData.flags = pRoamScanConfig->flags;
752            memcpy(roamScanConfigVenData.roam_scan_config,
753                   pRoamScanConfig->roam_scan_config,
754                   sizeof(roamScanConfigVenData.roam_scan_config));
755
756            pTlv = addLoggerTlv(WIFI_TAG_VENDOR_SPECIFIC,
757                                sizeof(roam_scan_config_vendor_data_t),
758                                (u8 *)&roamScanConfigVenData, pTlv);
759            tot_len += sizeof(tlv_log) +
760                       sizeof(roam_scan_config_vendor_data_t);
761        }
762        break;
763    }
764
765    status = update_connectivity_ring_buf(info, pRingBufferEntry, tot_len);
766    if (status != WIFI_SUCCESS) {
767        ALOGE("Failed to write roam event into ring buffer");
768    }
769
770    return status;
771}
772
773wifi_error process_firmware_prints(hal_info *info, u8 *buf, u16 length)
774{
775    wifi_ring_buffer_entry rb_entry_hdr;
776    struct timeval time;
777    wifi_error status;
778
779    rb_entry_hdr.entry_size = length;
780    rb_entry_hdr.flags = RING_BUFFER_ENTRY_FLAGS_HAS_TIMESTAMP;
781    rb_entry_hdr.type = ENTRY_TYPE_DATA;
782    gettimeofday(&time, NULL);
783    rb_entry_hdr.timestamp = time.tv_usec + time.tv_sec * 1000 * 1000;
784
785    /* Write if verbose and handler is set */
786    if (info->rb_infos[FIRMWARE_PRINTS_RB_ID].verbose_level >= 1 &&
787        info->on_ring_buffer_data) {
788        /* Write header and payload separately to avoid
789         * complete payload memcpy */
790        status = ring_buffer_write(&info->rb_infos[FIRMWARE_PRINTS_RB_ID],
791                                   (u8*)&rb_entry_hdr,
792                                   sizeof(wifi_ring_buffer_entry),
793                                   0,
794                                   sizeof(wifi_ring_buffer_entry) + length);
795        if (status != WIFI_SUCCESS) {
796            ALOGE("Failed to write firmware prints rb header %d", status);
797            return status;
798        }
799        status = ring_buffer_write(&info->rb_infos[FIRMWARE_PRINTS_RB_ID],
800                                   buf, length, 1, length);
801        if (status != WIFI_SUCCESS) {
802            ALOGE("Failed to write firmware prints rb payload %d", status);
803            return status;
804        }
805    }
806
807    return WIFI_SUCCESS;
808}
809
810static wifi_error process_beacon_received_event(hal_info *info,
811                                      u8* buf, int length)
812{
813    wifi_ring_buffer_driver_connectivity_event *pConnectEvent;
814    wifi_ring_buffer_entry *pRingBufferEntry;
815    tlv_log *pTlv;
816    int tot_len = sizeof(wifi_ring_buffer_driver_connectivity_event);
817    u8 out_buf[RING_BUF_ENTRY_SIZE];
818    wlan_beacon_received_payload_type *pBeaconRcvd;
819    u32 rssi;
820    wifi_error status;
821
822    pRingBufferEntry = (wifi_ring_buffer_entry *)&out_buf[0];
823    memset(pRingBufferEntry, 0, RING_BUF_ENTRY_SIZE);
824    pConnectEvent = (wifi_ring_buffer_driver_connectivity_event *)
825                     (pRingBufferEntry + 1);
826
827    pBeaconRcvd = (wlan_beacon_received_payload_type *)buf;
828
829    pConnectEvent->event = WIFI_EVENT_BEACON_RECEIVED;
830    pTlv = &pConnectEvent->tlvs[0];
831
832    pTlv = addLoggerTlv(WIFI_TAG_BSSID, sizeof(pBeaconRcvd->bssid),
833                        (u8 *)pBeaconRcvd->bssid, pTlv);
834    tot_len += sizeof(tlv_log) + sizeof(pBeaconRcvd->bssid);
835
836    rssi = get_rssi(pBeaconRcvd->beacon_rssi);
837    pTlv = addLoggerTlv(WIFI_TAG_RSSI,
838            sizeof(rssi), (u8 *)&rssi, pTlv);
839    tot_len += sizeof(tlv_log) + sizeof(pBeaconRcvd->beacon_rssi);
840
841    status = update_connectivity_ring_buf(info, pRingBufferEntry, tot_len);
842    if (status != WIFI_SUCCESS) {
843        ALOGE("Failed to write addba event into ring buffer");
844    }
845
846    return status;
847}
848
849static wifi_error process_fw_diag_msg(hal_info *info, u8* buf, u16 length)
850{
851    u16 count = 0, id;
852    u16 payloadlen = 0;
853    u16 hdr_size = 0;
854    wifi_error status;
855    fw_diag_msg_fixed_hdr_t *diag_msg_fixed_hdr;
856    fw_diag_msg_hdr_t *diag_msg_hdr;
857    fw_diag_msg_hdr_v2_t *diag_msg_hdr_v2;
858    u8 *payload = NULL;
859
860    buf += 4;
861    length -= 4;
862
863    while (length > (count + sizeof(fw_diag_msg_fixed_hdr_t))) {
864        diag_msg_fixed_hdr = (fw_diag_msg_fixed_hdr_t *)(buf + count);
865        switch (diag_msg_fixed_hdr->diag_event_type) {
866            case WLAN_DIAG_TYPE_EVENT:
867            case WLAN_DIAG_TYPE_EVENT_V2:
868            {
869                if (WLAN_DIAG_TYPE_EVENT ==
870                        diag_msg_fixed_hdr->diag_event_type) {
871                    diag_msg_hdr = (fw_diag_msg_hdr_t *)diag_msg_fixed_hdr;
872                    id = diag_msg_hdr->diag_id;
873                    payloadlen = diag_msg_hdr->u.payload_len;
874                    hdr_size = sizeof(fw_diag_msg_hdr_t);
875                    payload = diag_msg_hdr->payload;
876                } else {
877                    diag_msg_hdr_v2 =
878                        (fw_diag_msg_hdr_v2_t *)diag_msg_fixed_hdr;
879                    id = diag_msg_hdr_v2->diag_id;
880                    payloadlen = diag_msg_hdr_v2->u.payload_len;
881                    hdr_size = sizeof(fw_diag_msg_hdr_v2_t);
882                    payload = diag_msg_hdr_v2->payload;
883                }
884                switch (id) {
885                    case EVENT_WLAN_BT_COEX_BT_SCO_START:
886                    case EVENT_WLAN_BT_COEX_BT_SCO_STOP:
887                    case EVENT_WLAN_BT_COEX_BT_HID_START:
888                    case EVENT_WLAN_BT_COEX_BT_HID_STOP:
889                        status = process_bt_coex_event(info, id,
890                                                       payload,
891                                                       payloadlen);
892                        if (status != WIFI_SUCCESS) {
893                            ALOGE("Failed to process bt_coex event");
894                            return status;
895                        }
896                        break;
897                    case EVENT_WLAN_BT_COEX_BT_SCAN_START:
898                    case EVENT_WLAN_BT_COEX_BT_SCAN_STOP:
899                        status = process_bt_coex_scan_event(info, id,
900                                                       payload,
901                                                       payloadlen);
902                        if (status != WIFI_SUCCESS) {
903                            ALOGE("Failed to process bt_coex_scan event");
904                            return status;
905                        }
906                        break;
907                   case EVENT_WLAN_EXTSCAN_CYCLE_STARTED:
908                   case EVENT_WLAN_EXTSCAN_CYCLE_COMPLETED:
909                   case EVENT_WLAN_EXTSCAN_BUCKET_STARTED:
910                   case EVENT_WLAN_EXTSCAN_BUCKET_COMPLETED:
911                   case EVENT_WLAN_EXTSCAN_FEATURE_STOP:
912                   case EVENT_WLAN_EXTSCAN_RESULTS_AVAILABLE:
913                        status = process_extscan_event(info, id,
914                                                       payload,
915                                                       payloadlen);
916                        if (status != WIFI_SUCCESS) {
917                            ALOGE("Failed to process extscan event");
918                            return status;
919                        }
920                        break;
921                   case EVENT_WLAN_ROAM_SCAN_STARTED:
922                   case EVENT_WLAN_ROAM_SCAN_COMPLETE:
923                   case EVENT_WLAN_ROAM_CANDIDATE_FOUND:
924                   case EVENT_WLAN_ROAM_SCAN_CONFIG:
925                        status = process_roam_event(info, id,
926                                                    payload,
927                                                    payloadlen);
928                        if (status != WIFI_SUCCESS) {
929                            ALOGE("Failed to process roam event");
930                            return status;
931                        }
932                        break;
933                   case EVENT_WLAN_ADD_BLOCK_ACK_SUCCESS:
934                        status = process_addba_success_event(info,
935                                                       payload,
936                                                       payloadlen);
937                        if (status != WIFI_SUCCESS) {
938                            ALOGE("Failed to process addba success event");
939                            return status;
940                        }
941                        break;
942                   case EVENT_WLAN_ADD_BLOCK_ACK_FAILED:
943                        status = process_addba_failed_event(info,
944                                                      payload,
945                                                      payloadlen);
946                        if (status != WIFI_SUCCESS) {
947                            ALOGE("Failed to process addba failed event");
948                            return status;
949                        }
950                        break;
951                   case EVENT_WLAN_BEACON_EVENT:
952                        status = process_beacon_received_event(info,
953                                                      payload,
954                                                      payloadlen);
955                        if (status != WIFI_SUCCESS) {
956                            ALOGE("Failed to process beacon received event");
957                            return status;
958                        }
959                        break;
960                   default:
961                        return WIFI_SUCCESS;
962                }
963            }
964            break;
965            case WLAN_DIAG_TYPE_LOG:
966            case WLAN_DIAG_TYPE_LOG_V2:
967            {
968                if (WLAN_DIAG_TYPE_LOG == diag_msg_fixed_hdr->diag_event_type) {
969                    diag_msg_hdr = (fw_diag_msg_hdr_t *)diag_msg_fixed_hdr;
970                    id = diag_msg_hdr->diag_id;
971                    payloadlen = diag_msg_hdr->u.payload_len;
972                    hdr_size = sizeof(fw_diag_msg_hdr_t);
973                    payload = diag_msg_hdr->payload;
974                } else {
975                    diag_msg_hdr_v2 = (fw_diag_msg_hdr_v2_t *)diag_msg_fixed_hdr;
976                    id = diag_msg_hdr_v2->diag_id;
977                    payloadlen = diag_msg_hdr_v2->u.payload_len;
978                    hdr_size = sizeof(fw_diag_msg_hdr_v2_t);
979                    payload = diag_msg_hdr_v2->payload;
980                }
981                switch (id) {
982                case LOG_WLAN_EXTSCAN_CAPABILITIES:
983                    status = process_log_extscan_capabilities(info,
984                                                    payload,
985                                                    payloadlen);
986                    if (status != WIFI_SUCCESS) {
987                        ALOGE("Failed to process extscan capabilities");
988                        return status;
989                    }
990                    break;
991                default:
992                    break;
993                }
994            }
995            break;
996            case WLAN_DIAG_TYPE_MSG:
997                diag_msg_hdr = (fw_diag_msg_hdr_t *)diag_msg_fixed_hdr;
998                id = diag_msg_hdr->diag_id;
999                /* Length field is only one byte for WLAN_DIAG_TYPE_MSG */
1000                payloadlen = diag_msg_hdr->u.msg_hdr.payload_len;
1001                hdr_size = sizeof(fw_diag_msg_hdr_t);
1002                payload = diag_msg_hdr->payload;
1003                process_firmware_prints(info, (u8 *)diag_msg_fixed_hdr,
1004                                       payloadlen + hdr_size);
1005                break;
1006            case WLAN_DIAG_TYPE_MSG_V2:
1007                diag_msg_hdr_v2 = (fw_diag_msg_hdr_v2_t *)diag_msg_fixed_hdr;
1008                id = diag_msg_hdr_v2->diag_id;
1009                /* Length field is only one byte for WLAN_DIAG_TYPE_MSG_V2 */
1010                payloadlen = diag_msg_hdr_v2->u.msg_hdr.payload_len;
1011                hdr_size = sizeof(fw_diag_msg_hdr_v2_t);
1012                payload = diag_msg_hdr_v2->payload;
1013                process_firmware_prints(info, (u8 *)diag_msg_fixed_hdr,
1014                                       payloadlen + hdr_size);
1015                break;
1016            case WLAN_DIAG_TYPE_CONFIG:
1017            {
1018                /* Base timestamp is part of this diag type */
1019                diag_msg_hdr = (fw_diag_msg_hdr_t *) diag_msg_fixed_hdr;
1020                id = diag_msg_hdr->diag_id;
1021                payload = diag_msg_hdr->payload;
1022                payloadlen = diag_msg_hdr->u.payload_len;
1023                hdr_size = sizeof(fw_diag_msg_hdr_t);
1024                process_firmware_prints(info, (u8 *)diag_msg_hdr,
1025                                        payloadlen + hdr_size);
1026            }
1027            break;
1028            default:
1029                return WIFI_SUCCESS;
1030        }
1031        count += payloadlen + hdr_size;
1032    }
1033    return WIFI_SUCCESS;
1034}
1035
1036static wifi_error remap_event(int in_event, int *out_event)
1037{
1038    int i = 0;
1039    while (i < MAX_CONNECTIVITY_EVENTS) {
1040        if (events[i].q_event == in_event) {
1041            *out_event = events[i].g_event;
1042            return WIFI_SUCCESS;
1043        }
1044        i++;
1045    }
1046    return WIFI_ERROR_UNKNOWN;
1047}
1048
1049static wifi_error process_wlan_pe_event(hal_info *info, u8* buf, int length)
1050{
1051    wlan_pe_event_t *pWlanPeEvent;
1052    pe_event_vendor_data_t peEventVenData;
1053    wifi_ring_buffer_driver_connectivity_event *pConnectEvent;
1054    wifi_ring_buffer_entry *pRingBufferEntry;
1055    tlv_log *pTlv;
1056    int tot_len = sizeof(wifi_ring_buffer_driver_connectivity_event);
1057    u8 out_buf[RING_BUF_ENTRY_SIZE];
1058    wifi_error status;
1059
1060    pWlanPeEvent = (wlan_pe_event_t *)buf;
1061
1062    pRingBufferEntry = (wifi_ring_buffer_entry *)&out_buf[0];
1063    memset(pRingBufferEntry, 0, RING_BUF_ENTRY_SIZE);
1064    pConnectEvent = (wifi_ring_buffer_driver_connectivity_event *)
1065                     (pRingBufferEntry + 1);
1066
1067    status = remap_event(pWlanPeEvent->event_type,
1068                         (int *)&pConnectEvent->event);
1069    if (status != WIFI_SUCCESS)
1070        return status;
1071
1072    pTlv = &pConnectEvent->tlvs[0];
1073    pTlv = addLoggerTlv(WIFI_TAG_BSSID, sizeof(pWlanPeEvent->bssid),
1074                        (u8 *)pWlanPeEvent->bssid, pTlv);
1075    tot_len += sizeof(tlv_log) + sizeof(pWlanPeEvent->bssid);
1076
1077    tot_len += add_status_tag(&pTlv, (int)pWlanPeEvent->status);
1078
1079    pTlv = addLoggerTlv(WIFI_TAG_REASON_CODE, sizeof(pWlanPeEvent->reason_code),
1080                        (u8 *)&pWlanPeEvent->reason_code, pTlv);
1081    tot_len += sizeof(tlv_log) + sizeof(pWlanPeEvent->reason_code);
1082
1083    peEventVenData.sme_state = pWlanPeEvent->sme_state;
1084    peEventVenData.mlm_state = pWlanPeEvent->mlm_state;
1085
1086    pTlv = addLoggerTlv(WIFI_TAG_VENDOR_SPECIFIC,
1087                        sizeof(pe_event_vendor_data_t),
1088                        (u8 *)&peEventVenData, pTlv);
1089    tot_len += sizeof(tlv_log) + sizeof(pe_event_vendor_data_t);
1090
1091    status = update_connectivity_ring_buf(info, pRingBufferEntry, tot_len);
1092    if (status != WIFI_SUCCESS) {
1093        ALOGE("Failed to write pe event into ring buffer");
1094    }
1095
1096    return status;
1097}
1098
1099static wifi_error process_wlan_eapol_event(hal_info *info, u8* buf, int length)
1100{
1101    wifi_ring_buffer_driver_connectivity_event *pConnectEvent;
1102    wlan_eapol_event_t *pWlanEapolEvent;
1103    wifi_ring_buffer_entry *pRingBufferEntry;
1104    u8 out_buf[RING_BUF_ENTRY_SIZE];
1105    int tot_len = sizeof(wifi_ring_buffer_driver_connectivity_event);
1106    tlv_log *pTlv;
1107    u32 eapol_msg_type = 0;
1108    wifi_error status;
1109
1110    pWlanEapolEvent = (wlan_eapol_event_t *)buf;
1111    pRingBufferEntry = (wifi_ring_buffer_entry *)&out_buf[0];
1112    memset(pRingBufferEntry, 0, RING_BUF_ENTRY_SIZE);
1113    pConnectEvent = (wifi_ring_buffer_driver_connectivity_event *)
1114                     (pRingBufferEntry + 1);
1115
1116    if (pWlanEapolEvent->event_sub_type ==
1117        WLAN_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED)
1118        pConnectEvent->event = WIFI_EVENT_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED;
1119    else
1120        pConnectEvent->event = WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED;
1121
1122    pTlv = &pConnectEvent->tlvs[0];
1123
1124    if ((pWlanEapolEvent->eapol_key_info & EAPOL_MASK) == EAPOL_M1_MASK)
1125        eapol_msg_type = 1;
1126    else if ((pWlanEapolEvent->eapol_key_info & EAPOL_MASK) == EAPOL_M2_MASK)
1127        eapol_msg_type = 2;
1128    else if ((pWlanEapolEvent->eapol_key_info & EAPOL_MASK) == EAPOL_M3_MASK)
1129        eapol_msg_type = 3;
1130    else if ((pWlanEapolEvent->eapol_key_info & EAPOL_MASK) == EAPOL_M4_MASK)
1131        eapol_msg_type = 4;
1132    else
1133        ALOGI("Unknown EAPOL message type \n");
1134    pTlv = addLoggerTlv(WIFI_TAG_EAPOL_MESSAGE_TYPE, sizeof(u32),
1135                        (u8 *)&eapol_msg_type, pTlv);
1136    tot_len += sizeof(tlv_log) + sizeof(u32);
1137    pTlv = addLoggerTlv(WIFI_TAG_ADDR1, sizeof(pWlanEapolEvent->dest_addr),
1138                        (u8 *)pWlanEapolEvent->dest_addr, pTlv);
1139    tot_len += sizeof(tlv_log) + sizeof(pWlanEapolEvent->dest_addr);
1140    pTlv = addLoggerTlv(WIFI_TAG_ADDR2, sizeof(pWlanEapolEvent->src_addr),
1141                        (u8 *)pWlanEapolEvent->src_addr, pTlv);
1142    tot_len += sizeof(tlv_log) + sizeof(pWlanEapolEvent->src_addr);
1143
1144    status = update_connectivity_ring_buf(info, pRingBufferEntry, tot_len);
1145    if (status != WIFI_SUCCESS) {
1146        ALOGE("Failed to write eapol event into ring buffer");
1147    }
1148
1149    return status;
1150}
1151
1152static wifi_error process_wakelock_event(hal_info *info, u8* buf, int length)
1153{
1154    wlan_wake_lock_event_t *pWlanWakeLockEvent;
1155    wake_lock_event *pWakeLockEvent;
1156    wifi_power_event *pPowerEvent;
1157    tlv_log *pTlv;
1158    wifi_ring_buffer_entry *pRingBufferEntry;
1159    u16 len_ring_buffer_entry;
1160    struct timeval time;
1161    wifi_error status;
1162    u8 wl_ring_buffer[RING_BUF_ENTRY_SIZE];
1163    u16 entry_size;
1164
1165    pWlanWakeLockEvent = (wlan_wake_lock_event_t *)(buf);
1166    entry_size = sizeof(wifi_power_event) +
1167                 sizeof(tlv_log) +
1168                 sizeof(wake_lock_event) +
1169                 pWlanWakeLockEvent->name_len + 1;
1170    len_ring_buffer_entry = sizeof(wifi_ring_buffer_entry) + entry_size;
1171
1172    if (len_ring_buffer_entry > RING_BUF_ENTRY_SIZE) {
1173        pRingBufferEntry = (wifi_ring_buffer_entry *)malloc(
1174                len_ring_buffer_entry);
1175        if (pRingBufferEntry == NULL) {
1176            ALOGE("%s: Failed to allocate memory", __FUNCTION__);
1177            return WIFI_ERROR_OUT_OF_MEMORY;
1178        }
1179    } else {
1180        pRingBufferEntry = (wifi_ring_buffer_entry *)wl_ring_buffer;
1181    }
1182
1183    pPowerEvent = (wifi_power_event *)(pRingBufferEntry + 1);
1184    pPowerEvent->event = WIFI_TAG_WAKE_LOCK_EVENT;
1185
1186    pTlv = &pPowerEvent->tlvs[0];
1187    pTlv->tag = WIFI_TAG_WAKE_LOCK_EVENT;
1188    pTlv->length = sizeof(wake_lock_event) +
1189                   pWlanWakeLockEvent->name_len + 1;
1190
1191    pWakeLockEvent = (wake_lock_event *)pTlv->value;
1192    pWakeLockEvent->status = pWlanWakeLockEvent->status;
1193    pWakeLockEvent->reason = pWlanWakeLockEvent->reason;
1194    memcpy(pWakeLockEvent->name, pWlanWakeLockEvent->name,
1195           pWlanWakeLockEvent->name_len);
1196
1197    pRingBufferEntry->entry_size = entry_size;
1198    pRingBufferEntry->flags = RING_BUFFER_ENTRY_FLAGS_HAS_BINARY |
1199                              RING_BUFFER_ENTRY_FLAGS_HAS_TIMESTAMP;
1200    pRingBufferEntry->type = ENTRY_TYPE_POWER_EVENT;
1201    gettimeofday(&time, NULL);
1202    pRingBufferEntry->timestamp = time.tv_usec + time.tv_sec * 1000 * 1000;
1203
1204    /* Write if verbose and handler is set */
1205    if (info->rb_infos[POWER_EVENTS_RB_ID].verbose_level >= 1 &&
1206        info->on_ring_buffer_data) {
1207        status = ring_buffer_write(&info->rb_infos[POWER_EVENTS_RB_ID],
1208                                   (u8*)pRingBufferEntry,
1209                                   len_ring_buffer_entry,
1210                                   1,
1211                                   len_ring_buffer_entry);
1212    } else {
1213        status = WIFI_SUCCESS;
1214    }
1215
1216    if ((u8 *)pRingBufferEntry != wl_ring_buffer) {
1217        ALOGI("Message with more than RING_BUF_ENTRY_SIZE");
1218        free(pRingBufferEntry);
1219    }
1220
1221    return status;
1222}
1223
1224static void process_wlan_log_complete_event(hal_info *info,
1225                                                  u8* buf,
1226                                                  int length)
1227{
1228    wlan_log_complete_event_t *lfd_event;
1229
1230    ALOGV("Received log completion event from driver");
1231    lfd_event = (wlan_log_complete_event_t *)buf;
1232
1233    push_out_all_ring_buffers(info);
1234
1235    if (lfd_event->is_fatal == WLAN_LOG_TYPE_FATAL) {
1236        ALOGE("Received fatal event, sending alert");
1237        send_alert(info, lfd_event->reason_code);
1238    }
1239}
1240
1241
1242static void process_wlan_low_resource_failure(hal_info *info,
1243                                              u8* buf,
1244                                              u16 length)
1245{
1246    wifi_ring_buffer_driver_connectivity_event *pConnectEvent;
1247    wlan_low_resource_failure_event_t *pWlanResourceEvent;
1248    resource_failure_vendor_data_t cap_vendor_data;
1249    wifi_ring_buffer_entry *pRingBufferEntry;
1250    u8 out_buf[RING_BUF_ENTRY_SIZE];
1251    int tot_len = sizeof(wifi_ring_buffer_driver_connectivity_event);
1252    tlv_log *pTlv;
1253    wifi_error status;
1254
1255    pWlanResourceEvent = (wlan_low_resource_failure_event_t *)buf;
1256    pRingBufferEntry = (wifi_ring_buffer_entry *)&out_buf[0];
1257    memset(pRingBufferEntry, 0, RING_BUF_ENTRY_SIZE);
1258    pConnectEvent = (wifi_ring_buffer_driver_connectivity_event *)
1259                     (pRingBufferEntry + 1);
1260
1261    pConnectEvent->event = WIFI_EVENT_MEM_ALLOC_FAILURE;
1262    memset(&cap_vendor_data, 0, sizeof(resource_failure_vendor_data_t));
1263
1264    if (length > sizeof(resource_failure_vendor_data_t)) {
1265        ALOGE("Received resource failure event of size : %d, whereas expected"
1266              " size is <= %zu bytes", length,
1267              sizeof(resource_failure_vendor_data_t));
1268        return;
1269    }
1270    memcpy(&cap_vendor_data, pWlanResourceEvent, length);
1271
1272    pTlv = &pConnectEvent->tlvs[0];
1273    pTlv = addLoggerTlv(WIFI_TAG_VENDOR_SPECIFIC,
1274                        sizeof(resource_failure_vendor_data_t),
1275                        (u8 *)&cap_vendor_data, pTlv);
1276    tot_len += sizeof(tlv_log) + sizeof(resource_failure_vendor_data_t);
1277
1278    status = update_connectivity_ring_buf(info, pRingBufferEntry, tot_len);
1279    if (status != WIFI_SUCCESS) {
1280        ALOGE("Failed to write resource failure event into ring buffer");
1281    }
1282}
1283
1284
1285static wifi_error update_stats_to_ring_buf(hal_info *info,
1286                      u8 *rb_entry, u32 size)
1287{
1288    int num_records = 1;
1289    wifi_ring_buffer_entry *pRingBufferEntry =
1290        (wifi_ring_buffer_entry *)rb_entry;
1291    struct timeval time;
1292
1293    pRingBufferEntry->entry_size = size - sizeof(wifi_ring_buffer_entry);
1294    pRingBufferEntry->flags = RING_BUFFER_ENTRY_FLAGS_HAS_BINARY |
1295                              RING_BUFFER_ENTRY_FLAGS_HAS_TIMESTAMP;
1296    pRingBufferEntry->type = ENTRY_TYPE_PKT;
1297    gettimeofday(&time,NULL);
1298    pRingBufferEntry->timestamp = time.tv_usec + time.tv_sec * 1000 * 1000;
1299
1300    // Write if verbose and handler is set
1301    if ((info->rb_infos[PKT_STATS_RB_ID].verbose_level >= VERBOSE_DEBUG_PROBLEM)
1302        && info->on_ring_buffer_data) {
1303        ring_buffer_write(&info->rb_infos[PKT_STATS_RB_ID],
1304                          (u8*)pRingBufferEntry,
1305                          size,
1306                          num_records,
1307                          size);
1308    }
1309
1310    return WIFI_SUCCESS;
1311}
1312
1313static u16 get_rate(u16 mcs_r)
1314{
1315    u16 tx_rate = 0;
1316    MCS mcs;
1317    static u16 rate_lookup[][8] = {{96, 48, 24, 12, 108, 72, 36, 18},
1318                            {22, 11,  4,  2,  22, 11,  4,  0}};
1319    static u16 MCS_rate_lookup_ht[][8] =
1320                                  {{ 13,  14,  27,  30,  59,  65,  117,  130},
1321                                   { 26,  29,  54,  60, 117, 130,  234,  260},
1322                                   { 39,  43,  81,  90, 176, 195,  351,  390},
1323                                   { 52,  58, 108, 120, 234, 260,  468,  520},
1324                                   { 78,  87, 162, 180, 351, 390,  702,  780},
1325                                   {104, 116, 216, 240, 468, 520,  936, 1040},
1326                                   {117, 130, 243, 270, 527, 585, 1053, 1170},
1327                                   {130, 144, 270, 300, 585, 650, 1170, 1300},
1328                                   {156, 173, 324, 360, 702, 780, 1404, 1560},
1329                                   {  0,   0, 360, 400, 780, 867, 1560, 1733},
1330                                   { 26,  29,  54,  60, 117, 130,  234,  260},
1331                                   { 52,  58, 108, 120, 234, 260,  468,  520},
1332                                   { 78,  87, 162, 180, 351, 390,  702,  780},
1333                                   {104, 116, 216, 240, 468, 520,  936, 1040},
1334                                   {156, 173, 324, 360, 702, 780, 1404, 1560},
1335                                   {208, 231, 432, 480, 936,1040, 1872, 2080},
1336                                   {234, 261, 486, 540,1053,1170, 2106, 2340},
1337                                   {260, 289, 540, 600,1170,1300, 2340, 2600},
1338                                   {312, 347, 648, 720,1404,1560, 2808, 3120},
1339                                   {  0,   0, 720, 800,1560,1733, 3120, 3467}};
1340
1341    mcs.mcs = mcs_r;
1342    if ((mcs.mcs_s.preamble <= WL_PREAMBLE_VHT) && (mcs.mcs_s.rate < 10)) {
1343        switch(mcs.mcs_s.preamble)
1344        {
1345            case WL_PREAMBLE_CCK:
1346            case WL_PREAMBLE_OFDM:
1347                if(mcs.mcs_s.rate<8) {
1348                    tx_rate = rate_lookup [mcs.mcs_s.preamble][mcs.mcs_s.rate];
1349                    if (mcs.mcs_s.nss)
1350                        tx_rate *=2;
1351                } else {
1352                    ALOGE("Unexpected rate value");
1353                }
1354            break;
1355            case WL_PREAMBLE_HT:
1356                if(mcs.mcs_s.rate<8) {
1357                    if (!mcs.mcs_s.nss)
1358                        tx_rate = MCS_rate_lookup_ht[mcs.mcs_s.rate]
1359                                        [2*mcs.mcs_s.bw+mcs.mcs_s.short_gi];
1360                    else
1361                        tx_rate = MCS_rate_lookup_ht[10+mcs.mcs_s.rate]
1362                                        [2*mcs.mcs_s.bw+mcs.mcs_s.short_gi];
1363                } else {
1364                    ALOGE("Unexpected HT mcs.mcs_s index");
1365                }
1366            break;
1367            case WL_PREAMBLE_VHT:
1368                if (!mcs.mcs_s.nss)
1369                    tx_rate = MCS_rate_lookup_ht[mcs.mcs_s.rate]
1370                                        [2*mcs.mcs_s.bw+mcs.mcs_s.short_gi];
1371                else
1372                    tx_rate = MCS_rate_lookup_ht[10+mcs.mcs_s.rate]
1373                                        [2*mcs.mcs_s.bw+mcs.mcs_s.short_gi];
1374            break;
1375            default:
1376                ALOGE("Unexpected preamble");
1377        }
1378    }
1379    return tx_rate;
1380}
1381
1382static wifi_error populate_rx_aggr_stats(hal_info *info)
1383{
1384    wifi_error status;
1385    wifi_ring_buffer_entry *pRingBufferEntry = info->rx_aggr_pkts;
1386    wifi_ring_per_packet_status_entry *pps_entry;
1387    u32 index = 0;
1388
1389    while (index < info->rx_buf_size_occupied) {
1390        pps_entry = (wifi_ring_per_packet_status_entry *)(pRingBufferEntry + 1);
1391
1392        pps_entry->MCS = info->aggr_stats.RxMCS.mcs;
1393        pps_entry->last_transmit_rate = info->aggr_stats.last_transmit_rate;
1394        pps_entry->rssi = info->aggr_stats.rssi;
1395        pps_entry->firmware_entry_timestamp = info->aggr_stats.timestamp;
1396        pps_entry->tid = info->aggr_stats.tid;
1397
1398        index += pRingBufferEntry->entry_size;
1399        status = update_stats_to_ring_buf(info, (u8 *)pRingBufferEntry,
1400                pRingBufferEntry->entry_size);
1401
1402        if (status != WIFI_SUCCESS) {
1403            ALOGE("Failed to write Rx stats into the ring buffer");
1404            return status;
1405        }
1406        /* update_stats_to_ring_buf() modifies the size. Update the same again
1407         * here by adding sizeof(wifi_ring_buffer_entry) to continue parsing
1408         */
1409        pRingBufferEntry = (wifi_ring_buffer_entry *)((u8 *)pRingBufferEntry
1410                            + sizeof(wifi_ring_buffer_entry)
1411                            + pRingBufferEntry->entry_size);
1412    }
1413    memset(info->rx_aggr_pkts, 0, info->rx_buf_size_occupied);
1414    info->rx_buf_size_occupied = 0;
1415
1416    return WIFI_SUCCESS;
1417}
1418
1419static wifi_error parse_rx_stats(hal_info *info, u8 *buf, u16 size)
1420{
1421    wifi_error status = WIFI_SUCCESS;
1422    rb_pkt_stats_t *rx_stats_rcvd = (rb_pkt_stats_t *)buf;
1423    wifi_ring_buffer_entry *pRingBufferEntry;
1424    u32 len_ring_buffer_entry = 0;
1425
1426    if (size < sizeof(rb_pkt_stats_t)) {
1427        ALOGE("%s Unexpected rx stats event length: %d", __FUNCTION__, size);
1428        memset(info->rx_aggr_pkts, 0, info->rx_buf_size_occupied);
1429        memset(&info->aggr_stats, 0, sizeof(rx_aggr_stats));
1430        info->rx_buf_size_occupied = 0;
1431        return WIFI_ERROR_UNKNOWN;
1432    }
1433
1434    len_ring_buffer_entry = sizeof(wifi_ring_buffer_entry)
1435                            + sizeof(wifi_ring_per_packet_status_entry)
1436                            + RX_HTT_HDR_STATUS_LEN;
1437
1438    if (len_ring_buffer_entry + info->rx_buf_size_occupied
1439            > info->rx_buf_size_allocated) {
1440        wifi_ring_buffer_entry *temp;
1441        temp = (wifi_ring_buffer_entry *)realloc(info->rx_aggr_pkts,
1442                len_ring_buffer_entry + info->rx_buf_size_occupied);
1443        if (temp == NULL) {
1444            ALOGE("%s: Failed to reallocate memory", __FUNCTION__);
1445            free(info->rx_aggr_pkts);
1446            info->rx_aggr_pkts = NULL;
1447            return WIFI_ERROR_OUT_OF_MEMORY;
1448        }
1449        info->rx_aggr_pkts = temp;
1450        memset((u8 *)info->rx_aggr_pkts + info->rx_buf_size_allocated, 0,
1451                len_ring_buffer_entry + info->rx_buf_size_occupied
1452                - info->rx_buf_size_allocated);
1453        info->rx_buf_size_allocated =
1454            len_ring_buffer_entry + info->rx_buf_size_occupied;
1455    }
1456
1457    pRingBufferEntry = (wifi_ring_buffer_entry *)((u8 *)info->rx_aggr_pkts
1458            + info->rx_buf_size_occupied);
1459
1460    info->rx_buf_size_occupied += len_ring_buffer_entry;
1461
1462    /* Fill size of the entry in rb entry which can be used while populating
1463     * the data. Actual size that needs to be sent to ring buffer is only pps
1464     * entry size
1465     */
1466    pRingBufferEntry->entry_size = len_ring_buffer_entry;
1467    wifi_ring_per_packet_status_entry *rb_pkt_stats =
1468        (wifi_ring_per_packet_status_entry *)(pRingBufferEntry + 1);
1469
1470    memset(rb_pkt_stats, 0, sizeof(wifi_ring_per_packet_status_entry));
1471
1472    /* Peer tx packet and it is an Rx packet for us */
1473    rb_pkt_stats->flags |= PER_PACKET_ENTRY_FLAGS_DIRECTION_TX;
1474
1475    if (!((rx_stats_rcvd->mpdu_end.overflow_err) ||
1476          (rx_stats_rcvd->attention.fcs_err) ||
1477          (rx_stats_rcvd->attention.mpdu_length_err) ||
1478          (rx_stats_rcvd->attention.msdu_length_err) ||
1479          (rx_stats_rcvd->attention.tkip_mic_err) ||
1480          (rx_stats_rcvd->attention.decrypt_err)))
1481        rb_pkt_stats->flags |= PER_PACKET_ENTRY_FLAGS_TX_SUCCESS;
1482
1483    rb_pkt_stats->flags |= PER_PACKET_ENTRY_FLAGS_80211_HEADER;
1484
1485    if (rx_stats_rcvd->mpdu_start.encrypted)
1486        rb_pkt_stats->flags |= PER_PACKET_ENTRY_FLAGS_PROTECTED;
1487
1488    if (rx_stats_rcvd->attention.first_mpdu) {
1489        MCS *mcs = &info->aggr_stats.RxMCS;
1490        u32 ht_vht_sig;
1491
1492        /* Flush the cached stats as this is the first MPDU. */
1493        memset(&info->aggr_stats, 0, sizeof(rx_aggr_stats));
1494        if (rx_stats_rcvd->ppdu_start.preamble_type == PREAMBLE_L_SIG_RATE) {
1495            if (rx_stats_rcvd->ppdu_start.l_sig_rate_select)
1496                mcs->mcs_s.preamble = WL_PREAMBLE_OFDM;
1497            mcs->mcs_s.rate = rx_stats_rcvd->ppdu_start.l_sig_rate - 8;
1498            /*BW is 0 for legacy cases*/
1499        } else if (rx_stats_rcvd->ppdu_start.preamble_type ==
1500                   PREAMBLE_VHT_SIG_A_1) {
1501            ht_vht_sig = rx_stats_rcvd->ppdu_start.ht_sig_vht_sig_a_1;
1502            mcs->mcs_s.nss = ((ht_vht_sig >> 3) & 0x3);
1503            mcs->mcs_s.preamble = WL_PREAMBLE_HT;
1504            mcs->mcs_s.rate = (ht_vht_sig & BITMASK(7)) >> 3;
1505            mcs->mcs_s.bw = ((ht_vht_sig >> 7) & 1);
1506            mcs->mcs_s.short_gi =
1507                    ((rx_stats_rcvd->ppdu_start.ht_sig_vht_sig_a_2 >> 7) & 1);
1508        } else if (rx_stats_rcvd->ppdu_start.preamble_type ==
1509                   PREAMBLE_VHT_SIG_A_2) {
1510            ht_vht_sig = rx_stats_rcvd->ppdu_start.ht_sig_vht_sig_a_1;
1511            mcs->mcs_s.nss = ((ht_vht_sig >> 10) & 0x3);
1512            mcs->mcs_s.preamble = WL_PREAMBLE_VHT;
1513            mcs->mcs_s.rate =
1514                (rx_stats_rcvd->ppdu_start.ht_sig_vht_sig_a_2 >> 4) & BITMASK(4);
1515            mcs->mcs_s.bw = (ht_vht_sig & 3);
1516            mcs->mcs_s.short_gi =
1517                             (rx_stats_rcvd->ppdu_start.ht_sig_vht_sig_a_2 & 1);
1518        }
1519
1520        info->aggr_stats.last_transmit_rate
1521            = get_rate(info->aggr_stats.RxMCS.mcs);
1522
1523        info->aggr_stats.rssi = rx_stats_rcvd->ppdu_start.rssi_comb;
1524        info->aggr_stats.tid = rx_stats_rcvd->mpdu_start.tid;
1525    }
1526    rb_pkt_stats->link_layer_transmit_sequence
1527        = rx_stats_rcvd->mpdu_start.seq_num;
1528
1529    memcpy(&rb_pkt_stats->data[0], &rx_stats_rcvd->rx_hdr_status[0],
1530        RX_HTT_HDR_STATUS_LEN);
1531
1532    if ((rx_stats_rcvd->attention.last_mpdu
1533         && rx_stats_rcvd->msdu_end.last_msdu)
1534        || (rx_stats_rcvd->attention.first_mpdu
1535         && rx_stats_rcvd->attention.last_mpdu)) {
1536        info->aggr_stats.timestamp = rx_stats_rcvd->ppdu_end.tsf_timestamp;
1537        status = populate_rx_aggr_stats(info);
1538    }
1539
1540    return status;
1541}
1542
1543static u16 get_tx_mcs(u8 series,
1544                      struct tx_ppdu_start *ppdu_start)
1545{
1546    MCS mcs;
1547    struct series_bw *sbw = NULL;
1548
1549    mcs.mcs = 0;
1550
1551    if (series == 0) {
1552        if (ppdu_start->valid_s0_bw20)
1553            sbw = &ppdu_start->s0_bw20;
1554        else if (ppdu_start->valid_s0_bw40)
1555            sbw = &ppdu_start->s0_bw40;
1556        else if (ppdu_start->valid_s0_bw80)
1557            sbw = &ppdu_start->s0_bw80;
1558        else if (ppdu_start->valid_s0_bw160)
1559            sbw = &ppdu_start->s0_bw160;
1560    } else {
1561        if (ppdu_start->valid_s1_bw20)
1562            sbw = &ppdu_start->s1_bw20;
1563        else if (ppdu_start->valid_s1_bw40)
1564            sbw = &ppdu_start->s1_bw40;
1565        else if (ppdu_start->valid_s1_bw80)
1566            sbw = &ppdu_start->s1_bw80;
1567        else if (ppdu_start->valid_s1_bw160)
1568            sbw = &ppdu_start->s1_bw160;
1569    }
1570
1571    if (sbw) {
1572        mcs.mcs_s.rate      = sbw->rate;
1573        mcs.mcs_s.nss       = sbw->nss;
1574        mcs.mcs_s.preamble  = sbw->preamble_type;
1575        mcs.mcs_s.short_gi  = sbw->short_gi;
1576    }
1577
1578    return mcs.mcs;
1579}
1580
1581static void get_tx_aggr_stats(struct tx_ppdu_start *ppdu_start, hal_info *info)
1582{
1583    u32 baBitmap0 = 0;
1584    u32 baBitmap1 = 0;
1585
1586    info->pkt_stats->tx_seqnum_bitmap_31_0 = ppdu_start->seqnum_bitmap_31_0;
1587    info->pkt_stats->tx_seqnum_bitmap_63_32 = ppdu_start->seqnum_bitmap_63_32;
1588
1589    if (info->pkt_stats->isBlockAck) {
1590        int baShift = ppdu_start->start_seq_num - info->pkt_stats->ba_seq_num;
1591        //There are 4 scenarios in total:
1592        //1.TxSeq No. >= BaSeq No. and no roll over.
1593        //2.TxSeq No. >= BaSeq No. and TxSeq No. rolls over.
1594        //3.TxSeq No. <= BaSeq No. and no roll over.
1595        //4.TxSeq No. <= BaSeq No. and BaSeq No. rolls over.
1596
1597        baBitmap0 = info->pkt_stats->ba_bitmap_31_0;
1598        baBitmap1 = info->pkt_stats->ba_bitmap_63_32;
1599
1600        if (((baShift >= 0) && (baShift < SEQ_NUM_RANGE/2)) ||
1601            (baShift < -SEQ_NUM_RANGE/2)) {
1602            //Scenario No.1 and No.2
1603            baShift = baShift < -SEQ_NUM_RANGE/2 ? (SEQ_NUM_RANGE + baShift) :
1604                                                   baShift;
1605
1606            if (baShift < BITMAP_VAR_SIZE) {
1607                info->pkt_stats->shifted_bitmap_31_0 =
1608                    ((baBitmap1 << (32 - baShift)) | (baBitmap0 >> baShift));
1609                info->pkt_stats->shifted_bitmap_63_32 = baBitmap1 >> baShift;
1610            } else {
1611                info->pkt_stats->shifted_bitmap_31_0 =
1612                                       baBitmap1 >> (baShift - BITMAP_VAR_SIZE);
1613                info->pkt_stats->shifted_bitmap_63_32  = 0;
1614            }
1615        } else {
1616            baShift = (baShift >= SEQ_NUM_RANGE/2) ? (SEQ_NUM_RANGE - baShift) :
1617                                                      -baShift;
1618            if (baShift < BITMAP_VAR_SIZE) {
1619                info->pkt_stats->shifted_bitmap_31_0 = baBitmap0 << baShift;
1620                info->pkt_stats->shifted_bitmap_63_32 =
1621                                                ((baBitmap0 << (32 - baShift)) |
1622                                                 (baBitmap1 >> baShift));
1623            } else {
1624                info->pkt_stats->shifted_bitmap_31_0 = 0;
1625                info->pkt_stats->shifted_bitmap_63_32 =
1626                                      baBitmap0 << (baShift - BITMAP_VAR_SIZE);
1627            }
1628        }
1629    } else {
1630        info->pkt_stats->shifted_bitmap_31_0 = 0;
1631        info->pkt_stats->shifted_bitmap_63_32 = 0;
1632    }
1633}
1634
1635static void get_try_status_params(hal_info *info,
1636                                 struct tx_ppdu_end *tx_ppdu_end)
1637{
1638    int try_list_index;
1639
1640    if (tx_ppdu_end->stat.total_tries > 0)
1641        try_list_index = tx_ppdu_end->stat.total_tries - 1;
1642    else
1643        try_list_index = 0;
1644
1645    info->pkt_stats->tx_bandwidth =
1646        tx_ppdu_end->try_list.try_st[try_list_index].packet_bw;
1647    info->pkt_stats->series =
1648        tx_ppdu_end->try_list.try_st[try_list_index].series;
1649}
1650
1651static wifi_error parse_tx_stats(hal_info *info, void *buf,
1652                                 u32 buflen, u8 logtype)
1653{
1654    wifi_error status = WIFI_SUCCESS;
1655    int i;
1656    wifi_ring_buffer_entry *pRingBufferEntry =
1657        (wifi_ring_buffer_entry *)info->pkt_stats->tx_stats;
1658
1659    wifi_ring_per_packet_status_entry *rb_pkt_stats =
1660        (wifi_ring_per_packet_status_entry *)(pRingBufferEntry + 1);
1661
1662    ALOGV("Received Tx stats: log_type : %d", logtype);
1663    switch (logtype)
1664    {
1665        case PKTLOG_TYPE_TX_CTRL:
1666        {
1667            if (buflen < sizeof (wh_pktlog_txctl)) {
1668                ALOGE("Unexpected tx_ctrl event length: %d", buflen);
1669                return WIFI_ERROR_UNKNOWN;
1670            }
1671
1672            wh_pktlog_txctl *stats = (wh_pktlog_txctl *)buf;
1673            struct tx_ppdu_start *ppdu_start =
1674                (struct tx_ppdu_start *)(&stats->u.ppdu_start);
1675
1676            if (ppdu_start->frame_control & BIT(DATA_PROTECTED))
1677                rb_pkt_stats->flags |=
1678                    PER_PACKET_ENTRY_FLAGS_PROTECTED;
1679            rb_pkt_stats->link_layer_transmit_sequence
1680                = ppdu_start->start_seq_num;
1681            info->pkt_stats->start_seq_num = ppdu_start->start_seq_num;
1682            rb_pkt_stats->tid = ppdu_start->qos_ctl & 0xF;
1683            rb_pkt_stats->MCS = get_tx_mcs(info->pkt_stats->series, ppdu_start) |
1684                                (info->pkt_stats->tx_bandwidth << BW_OFFSET);
1685            rb_pkt_stats->last_transmit_rate = get_rate(rb_pkt_stats->MCS);
1686
1687            if (ppdu_start->ampdu)
1688                get_tx_aggr_stats(ppdu_start, info);
1689            info->pkt_stats->tx_stats_events |=  BIT(PKTLOG_TYPE_TX_CTRL);
1690        }
1691        break;
1692        case PKTLOG_TYPE_TX_STAT:
1693        {
1694            if (buflen < sizeof(struct tx_ppdu_end)) {
1695                ALOGE("Unexpected tx_stat event length: %d", buflen);
1696                return WIFI_ERROR_UNKNOWN;
1697            }
1698
1699            /* This should be the first event for tx-stats: So,
1700             * previous stats are invalid. Flush the old stats and treat
1701             * this as new packet
1702             */
1703            if (info->pkt_stats->tx_stats_events)
1704                memset(rb_pkt_stats, 0,
1705                        sizeof(wifi_ring_per_packet_status_entry));
1706
1707            struct tx_ppdu_end *tx_ppdu_end = (struct tx_ppdu_end*)(buf);
1708
1709            info->pkt_stats->ba_seq_num = tx_ppdu_end->stat.ba_start_seq_num;
1710            info->pkt_stats->isBlockAck = tx_ppdu_end->stat.ba_status;
1711
1712            if (tx_ppdu_end->stat.tx_ok)
1713                rb_pkt_stats->flags |= PER_PACKET_ENTRY_FLAGS_TX_SUCCESS;
1714            info->pkt_stats->isBlockAck = tx_ppdu_end->stat.ba_status;
1715
1716            info->pkt_stats->ba_bitmap_31_0 =  tx_ppdu_end->stat.ba_bitmap_31_0;
1717            info->pkt_stats->ba_bitmap_63_32 =
1718                                              tx_ppdu_end->stat.ba_bitmap_63_32;
1719            rb_pkt_stats->transmit_success_timestamp =
1720                tx_ppdu_end->try_list.try_st[0].timestamp;
1721            rb_pkt_stats->rssi = tx_ppdu_end->stat.ack_rssi_ave;
1722            rb_pkt_stats->num_retries = tx_ppdu_end->stat.total_tries;
1723            get_try_status_params(info, tx_ppdu_end);
1724
1725            info->pkt_stats->tx_stats_events |=  BIT(PKTLOG_TYPE_TX_STAT);
1726        }
1727        break;
1728        case PKTLOG_TYPE_TX_MSDU_ID:
1729        {
1730            memset(info->pkt_stats, 0, sizeof(struct pkt_stats_s));
1731            info->pkt_stats->num_msdu = *(u8 *)buf;
1732            info->pkt_stats->tx_stats_events =  BIT(PKTLOG_TYPE_TX_MSDU_ID);
1733        }
1734        break;
1735        case PKTLOG_TYPE_RC_UPDATE:
1736        case PKTLOG_TYPE_TX_FRM_HDR:
1737        case PKTLOG_TYPE_RC_FIND:
1738        case PKTLOG_TYPE_TX_VIRT_ADDR:
1739            ALOGV("%s : Unsupported log_type received : %d",
1740                  __FUNCTION__, logtype);
1741        break;
1742        default:
1743        {
1744            ALOGV("%s : Unexpected log_type received : %d",
1745                  __FUNCTION__, logtype);
1746            return WIFI_ERROR_UNKNOWN;
1747        }
1748    }
1749
1750    if ((info->pkt_stats->tx_stats_events &  BIT(PKTLOG_TYPE_TX_CTRL)) &&
1751        (info->pkt_stats->tx_stats_events &  BIT(PKTLOG_TYPE_TX_STAT)) &&
1752        (info->pkt_stats->tx_stats_events &  BIT(PKTLOG_TYPE_TX_MSDU_ID))) {
1753        /* No tx payload as of now, add the length to parameter size(3rd)
1754         * if there is any payload
1755         */
1756
1757        if (info->pkt_stats->num_msdu == 1) {
1758            if (!(rb_pkt_stats->flags & PER_PACKET_ENTRY_FLAGS_TX_SUCCESS))
1759                rb_pkt_stats->rssi = INVALID_RSSI;
1760            /* Handle non aggregated cases */
1761            status = update_stats_to_ring_buf(info,
1762                                     (u8 *)pRingBufferEntry,
1763                                     sizeof(wifi_ring_buffer_entry) +
1764                                     sizeof(wifi_ring_per_packet_status_entry));
1765            if (status != WIFI_SUCCESS) {
1766                ALOGE("Failed to write into the ring buffer : %d", logtype);
1767            }
1768        } else {
1769            /* Handle aggregated cases */
1770            for (i = 0; i < MAX_BA_WINDOW_SIZE; i++) {
1771                if (i < BITMAP_VAR_SIZE) {
1772                    if (info->pkt_stats->tx_seqnum_bitmap_31_0 & BIT(i)) {
1773                        if (info->pkt_stats->shifted_bitmap_31_0 & BIT(i)) {
1774                            rb_pkt_stats->flags |=
1775                                       PER_PACKET_ENTRY_FLAGS_TX_SUCCESS;
1776                        } else {
1777                            rb_pkt_stats->flags &=
1778                                       ~PER_PACKET_ENTRY_FLAGS_TX_SUCCESS;
1779                            rb_pkt_stats->rssi = INVALID_RSSI;
1780                        }
1781                    } else {
1782                        continue;
1783                    }
1784                } else {
1785                    if (info->pkt_stats->tx_seqnum_bitmap_63_32
1786                        & BIT(i - BITMAP_VAR_SIZE)) {
1787                        if (info->pkt_stats->shifted_bitmap_63_32
1788                            & BIT(i - BITMAP_VAR_SIZE)) {
1789                            rb_pkt_stats->flags |=
1790                                       PER_PACKET_ENTRY_FLAGS_TX_SUCCESS;
1791                        } else {
1792                            rb_pkt_stats->flags &=
1793                                       ~PER_PACKET_ENTRY_FLAGS_TX_SUCCESS;
1794                            rb_pkt_stats->rssi = INVALID_RSSI;
1795                        }
1796                    } else {
1797                        continue;
1798                    }
1799                }
1800                rb_pkt_stats->link_layer_transmit_sequence =
1801                                            info->pkt_stats->start_seq_num + i;
1802
1803                /* Take care of roll over SEQ_NUM_RANGE */
1804                rb_pkt_stats->link_layer_transmit_sequence &= 0xFFF;
1805
1806                status = update_stats_to_ring_buf(info,
1807                                     (u8 *)pRingBufferEntry,
1808                                     sizeof(wifi_ring_buffer_entry) +
1809                                     sizeof(wifi_ring_per_packet_status_entry));
1810                if (status != WIFI_SUCCESS) {
1811                    ALOGE("Failed to write into the ring buffer: %d", logtype);
1812                    break;
1813                }
1814            }
1815        }
1816
1817        /* Flush the local copy after writing the stats to ring buffer
1818         * for tx-stats.
1819         */
1820        info->pkt_stats->tx_stats_events = 0;
1821        memset(rb_pkt_stats, 0,
1822                sizeof(wifi_ring_per_packet_status_entry));
1823
1824    }
1825
1826    return status;
1827}
1828
1829wifi_error write_per_packet_stats_to_rb(hal_info *info, u8 *buf, u16 length)
1830{
1831    wifi_ring_buffer_entry rb_entry_hdr;
1832    struct timeval time;
1833    wifi_error status;
1834
1835    rb_entry_hdr.entry_size = length;
1836    rb_entry_hdr.flags = RING_BUFFER_ENTRY_FLAGS_HAS_TIMESTAMP;
1837    rb_entry_hdr.type = ENTRY_TYPE_PKT;
1838    gettimeofday(&time, NULL);
1839    rb_entry_hdr.timestamp = time.tv_usec + time.tv_sec * 1000 * 1000;
1840
1841    /* Write if verbose and handler is set */
1842    if (info->rb_infos[PKT_STATS_RB_ID].verbose_level >= 3 &&
1843        info->on_ring_buffer_data) {
1844        /* Write header and payload separately to avoid
1845         * complete payload memcpy */
1846        status = ring_buffer_write(&info->rb_infos[PKT_STATS_RB_ID],
1847                                   (u8*)&rb_entry_hdr,
1848                                   sizeof(wifi_ring_buffer_entry),
1849                                   0,
1850                                   sizeof(wifi_ring_buffer_entry) + length);
1851        if (status != WIFI_SUCCESS) {
1852            ALOGE("Failed to write driver prints rb header %d", status);
1853            return status;
1854        }
1855        status = ring_buffer_write(&info->rb_infos[PKT_STATS_RB_ID],
1856                                   buf,
1857                                   length,
1858                                   1,
1859                                   length);
1860        if (status != WIFI_SUCCESS) {
1861            ALOGE("Failed to write PKT stats into the ring buffer");
1862        }
1863    }
1864
1865    return WIFI_SUCCESS;
1866}
1867
1868static wifi_error parse_tx_pkt_fate_stats(hal_info *info, u8 *buf, u16 size)
1869{
1870    pktdump_hdr *log = (pktdump_hdr *)buf;
1871    wifi_tx_report_i *pkt_fate_stats;
1872
1873    if (info->pkt_fate_stats->n_tx_stats_collected >= MAX_FATE_LOG_LEN) {
1874        ALOGD("Only %u events are expected, don't process this event",
1875              MAX_FATE_LOG_LEN);
1876        return WIFI_SUCCESS;
1877    }
1878
1879    pkt_fate_stats = &info->pkt_fate_stats->tx_fate_stats[
1880                                   info->pkt_fate_stats->n_tx_stats_collected];
1881
1882    pkt_fate_stats->fate = (wifi_tx_packet_fate)log->status;
1883    if (log->type == TX_MGMT_PKT)
1884        pkt_fate_stats->frame_inf.payload_type = FRAME_TYPE_80211_MGMT;
1885    else
1886        pkt_fate_stats->frame_inf.payload_type = FRAME_TYPE_ETHERNET_II;
1887
1888    pkt_fate_stats->frame_inf.driver_timestamp_usec = log->driver_ts;
1889    pkt_fate_stats->frame_inf.firmware_timestamp_usec = log->fw_ts;
1890    pkt_fate_stats->frame_inf.frame_len = size - sizeof(pktdump_hdr);
1891    pkt_fate_stats->frame_inf.frame_content =
1892             (char *)malloc(pkt_fate_stats->frame_inf.frame_len * sizeof(char));
1893    if (pkt_fate_stats->frame_inf.frame_content) {
1894        memcpy(pkt_fate_stats->frame_inf.frame_content,
1895               buf + sizeof(pktdump_hdr), pkt_fate_stats->frame_inf.frame_len);
1896    } else {
1897        ALOGE("Failed to allocate mem for Tx frame_content for packet: %zu",
1898              info->pkt_fate_stats->n_tx_stats_collected);
1899        pkt_fate_stats->frame_inf.frame_len = 0;
1900    }
1901
1902    info->pkt_fate_stats->n_tx_stats_collected++;
1903
1904    return WIFI_SUCCESS;
1905}
1906
1907
1908static wifi_error parse_rx_pkt_fate_stats(hal_info *info, u8 *buf, u16 size)
1909{
1910    pktdump_hdr *log = (pktdump_hdr *)buf;
1911    wifi_rx_report_i *pkt_fate_stats;
1912
1913    if (info->pkt_fate_stats->n_rx_stats_collected >= MAX_FATE_LOG_LEN) {
1914        ALOGD("Only %u events are expected, don't process this event",
1915              MAX_FATE_LOG_LEN);
1916        return WIFI_SUCCESS;
1917    }
1918
1919    pkt_fate_stats = &info->pkt_fate_stats->rx_fate_stats[
1920                                   info->pkt_fate_stats->n_rx_stats_collected];
1921
1922    pkt_fate_stats->fate = (wifi_rx_packet_fate)log->status;
1923    if (log->type == RX_MGMT_PKT)
1924        pkt_fate_stats->frame_inf.payload_type = FRAME_TYPE_80211_MGMT;
1925    else
1926        pkt_fate_stats->frame_inf.payload_type = FRAME_TYPE_ETHERNET_II;
1927
1928    pkt_fate_stats->frame_inf.driver_timestamp_usec = log->driver_ts;
1929    pkt_fate_stats->frame_inf.firmware_timestamp_usec = log->fw_ts;
1930    pkt_fate_stats->frame_inf.frame_len = size - sizeof(pktdump_hdr);
1931    pkt_fate_stats->frame_inf.frame_content =
1932             (char *)malloc(pkt_fate_stats->frame_inf.frame_len * sizeof(char));
1933    if (pkt_fate_stats->frame_inf.frame_content) {
1934        memcpy(pkt_fate_stats->frame_inf.frame_content,
1935               buf + sizeof(pktdump_hdr), pkt_fate_stats->frame_inf.frame_len);
1936    } else {
1937        ALOGE("Failed to allocate mem for Rx frame_content for packet: %zu",
1938              info->pkt_fate_stats->n_rx_stats_collected);
1939        pkt_fate_stats->frame_inf.frame_len = 0;
1940    }
1941
1942    info->pkt_fate_stats->n_rx_stats_collected++;
1943
1944    return WIFI_SUCCESS;
1945}
1946
1947
1948static wifi_error trigger_fate_stats(hal_info *info, u8 *buf, u16 size)
1949{
1950    int i;
1951    packet_fate_monitor_info *pkt_fate_stats = info->pkt_fate_stats;
1952
1953    for (i=0; i<MAX_FATE_LOG_LEN; i++) {
1954        if (pkt_fate_stats->tx_fate_stats[i].frame_inf.frame_content) {
1955            free (pkt_fate_stats->tx_fate_stats[i].frame_inf.frame_content);
1956            pkt_fate_stats->tx_fate_stats[i].frame_inf.frame_content = NULL;
1957        }
1958
1959        if (pkt_fate_stats->rx_fate_stats[i].frame_inf.frame_content) {
1960            free (pkt_fate_stats->rx_fate_stats[i].frame_inf.frame_content);
1961            pkt_fate_stats->rx_fate_stats[i].frame_inf.frame_content = NULL;
1962        }
1963    }
1964    memset(pkt_fate_stats, 0, sizeof(packet_fate_monitor_info));
1965
1966    return WIFI_SUCCESS;
1967}
1968
1969
1970static wifi_error report_fate_stats(hal_info *info, u8 *buf, u16 size)
1971{
1972    ALOGI("Fate Tx-Rx: Packet fate stats stop received");
1973    return WIFI_SUCCESS;
1974}
1975
1976
1977static wifi_error parse_pkt_fate_stats(hal_info *info, u8 *buf, u16 size)
1978{
1979    pktdump_hdr *hdr = (pktdump_hdr *)buf;
1980
1981    switch (hdr->type)
1982    {
1983        case START_MONITOR:
1984            trigger_fate_stats(info, buf, size);
1985        break;
1986        case STOP_MONITOR:
1987            report_fate_stats(info, buf, size);
1988        break;
1989        case TX_MGMT_PKT:
1990        case TX_DATA_PKT:
1991            parse_tx_pkt_fate_stats(info, buf, size);
1992        break;
1993        case RX_MGMT_PKT:
1994        case RX_DATA_PKT:
1995            parse_rx_pkt_fate_stats(info, buf, size);
1996        break;
1997        default:
1998            ALOGE("Unsupported type : %d", hdr->type);
1999            return WIFI_ERROR_INVALID_ARGS;
2000    }
2001    return WIFI_SUCCESS;
2002}
2003
2004
2005static wifi_error parse_stats_record(hal_info *info,
2006                                     wh_pktlog_hdr_t *pkt_stats_header)
2007{
2008    wifi_error status;
2009    if (pkt_stats_header->log_type == PKTLOG_TYPE_PKT_STATS) {
2010        status = write_per_packet_stats_to_rb(info,
2011                                              (u8 *)(pkt_stats_header + 1),
2012                                              pkt_stats_header->size);
2013    } else if (pkt_stats_header->log_type == PKTLOG_TYPE_RX_STAT) {
2014        /* Ignore the event if it doesn't carry RX descriptor */
2015        if (pkt_stats_header->flags & PKT_INFO_FLG_RX_RXDESC_MASK)
2016            status = parse_rx_stats(info,
2017                                    (u8 *)(pkt_stats_header + 1),
2018                                    pkt_stats_header->size);
2019        else
2020            status = WIFI_SUCCESS;
2021    } else if (pkt_stats_header->log_type == PKTLOG_TYPE_PKT_DUMP ||
2022               pkt_stats_header->log_type == PKTLOG_TYPE_PKT_DUMP_V2) {
2023        pthread_mutex_lock(&info->pkt_fate_stats_lock);
2024        if (info->fate_monitoring_enabled) {
2025            if (pkt_stats_header->flags & PKT_INFO_FLG_PKT_DUMP_V2)
2026                status = parse_pkt_fate_stats(info,
2027                                              (u8 *)pkt_stats_header + sizeof(wh_pktlog_hdr_v2_t),
2028                                              pkt_stats_header->size);
2029            else
2030                status = parse_pkt_fate_stats(info,
2031                                              (u8 *)pkt_stats_header + sizeof(wh_pktlog_hdr_t),
2032                                              pkt_stats_header->size);
2033        } else
2034            status = WIFI_SUCCESS;
2035        pthread_mutex_unlock(&info->pkt_fate_stats_lock);
2036    } else {
2037        status = parse_tx_stats(info,
2038                                (u8 *)(pkt_stats_header + 1),
2039                                pkt_stats_header->size,
2040                                pkt_stats_header->log_type);
2041    }
2042    return status;
2043}
2044
2045static wifi_error parse_stats(hal_info *info, u8 *data, u32 buflen)
2046{
2047    wh_pktlog_hdr_t *pkt_stats_header;
2048    wifi_error status = WIFI_SUCCESS;
2049
2050    do {
2051        if (buflen < sizeof(wh_pktlog_hdr_t)) {
2052            status = WIFI_ERROR_INVALID_ARGS;
2053            break;
2054        }
2055
2056        pkt_stats_header = (wh_pktlog_hdr_t *)data;
2057
2058        if (buflen < (sizeof(wh_pktlog_hdr_t) + pkt_stats_header->size)) {
2059            status = WIFI_ERROR_INVALID_ARGS;
2060            break;
2061        }
2062        status = parse_stats_record(info, pkt_stats_header);
2063        if (status != WIFI_SUCCESS) {
2064            ALOGE("Failed to parse the stats type : %d",
2065                  pkt_stats_header->log_type);
2066            return status;
2067        }
2068        if (pkt_stats_header->flags & PKT_INFO_FLG_PKT_DUMP_V2){
2069            data += (sizeof(wh_pktlog_hdr_v2_t) + pkt_stats_header->size);
2070            buflen -= (sizeof(wh_pktlog_hdr_v2_t) + pkt_stats_header->size);
2071        } else {
2072            data += (sizeof(wh_pktlog_hdr_t) + pkt_stats_header->size);
2073            buflen -= (sizeof(wh_pktlog_hdr_t) + pkt_stats_header->size);
2074        }
2075    } while (buflen > 0);
2076
2077    return status;
2078}
2079
2080wifi_error process_driver_prints(hal_info *info, u8 *buf, u16 length)
2081{
2082    wifi_ring_buffer_entry rb_entry_hdr;
2083    struct timeval time;
2084    wifi_error status;
2085
2086    rb_entry_hdr.entry_size = length;
2087    rb_entry_hdr.flags = RING_BUFFER_ENTRY_FLAGS_HAS_TIMESTAMP;
2088    rb_entry_hdr.type = ENTRY_TYPE_DATA;
2089    gettimeofday(&time, NULL);
2090    rb_entry_hdr.timestamp = time.tv_usec + time.tv_sec * 1000 * 1000;
2091
2092    /* Write if verbose and handler is set */
2093    if (info->rb_infos[DRIVER_PRINTS_RB_ID].verbose_level >= 1 &&
2094        info->on_ring_buffer_data) {
2095        /* Write header and payload separately to avoid
2096         * complete payload memcpy */
2097        status = ring_buffer_write(&info->rb_infos[DRIVER_PRINTS_RB_ID],
2098                                   (u8*)&rb_entry_hdr,
2099                                   sizeof(wifi_ring_buffer_entry),
2100                                   0,
2101                                   sizeof(wifi_ring_buffer_entry) + length);
2102        if (status != WIFI_SUCCESS) {
2103            ALOGE("Failed to write driver prints rb header %d", status);
2104            return status;
2105        }
2106        status = ring_buffer_write(&info->rb_infos[DRIVER_PRINTS_RB_ID],
2107                                   buf, length, 1, length);
2108        if (status != WIFI_SUCCESS) {
2109            ALOGE("Failed to write driver prints rb payload %d", status);
2110            return status;
2111        }
2112    }
2113
2114    return WIFI_SUCCESS;
2115}
2116
2117wifi_error diag_message_handler(hal_info *info, nl_msg *msg)
2118{
2119    tAniNlHdr *wnl;
2120    u8 *buf;
2121    wifi_error status;
2122    tAniCLDHdr *clh = NULL;
2123    int cmd = 0;
2124
2125    if (info->cldctx) {
2126        struct nlattr *attrs[CLD80211_ATTR_MAX + 1];
2127        struct genlmsghdr *genlh;
2128        struct nlattr *tb_vendor[CLD80211_ATTR_MAX + 1];
2129        struct  nlmsghdr *nlh = nlmsg_hdr(msg);
2130
2131        genlh = (struct genlmsghdr *)nlmsg_data(nlh);
2132        if (genlh->cmd == ANI_NL_MSG_PUMAC ||
2133            genlh->cmd == ANI_NL_MSG_LOG ||
2134            genlh->cmd == ANI_NL_MSG_CNSS_DIAG) {
2135            cmd = genlh->cmd;
2136            int result = nla_parse(attrs, CLD80211_ATTR_MAX, genlmsg_attrdata(genlh, 0),
2137                    genlmsg_attrlen(genlh, 0), NULL);
2138
2139            if (!result && attrs[CLD80211_ATTR_VENDOR_DATA]) {
2140                nla_parse(tb_vendor, CLD80211_ATTR_MAX,
2141                          (struct nlattr *)nla_data(attrs[CLD80211_ATTR_VENDOR_DATA]),
2142                          nla_len(attrs[CLD80211_ATTR_VENDOR_DATA]), NULL);
2143
2144                if (tb_vendor[CLD80211_ATTR_DATA]) {
2145                    clh = (tAniCLDHdr *)nla_data(tb_vendor[CLD80211_ATTR_DATA]);
2146                }
2147            }
2148            if (!clh) {
2149                ALOGE("Invalid data received from driver");
2150                return WIFI_SUCCESS;
2151            }
2152        }
2153    } else {
2154        wnl = (tAniNlHdr *)nlmsg_hdr(msg);
2155        cmd = wnl->nlh.nlmsg_type;
2156    }
2157
2158    /* Check nlmsg_type also to avoid processing unintended msgs */
2159    if (cmd == ANI_NL_MSG_PUMAC) {
2160        if (!info->cldctx) {
2161            if ((wnl->nlh.nlmsg_len <= sizeof(tAniNlHdr)) ||
2162                (wnl->nlh.nlmsg_len < (sizeof(tAniNlHdr) + ntohs(wnl->clh.wmsg.length)))) {
2163                ALOGE("Received UMAC message with insufficent length: %d",
2164                      wnl->nlh.nlmsg_len);
2165                return WIFI_ERROR_UNKNOWN;
2166            }
2167            clh = &wnl->clh;
2168        }
2169        if (clh->wmsg.type == ANI_NL_MSG_LOG_HOST_EVENT_LOG_TYPE) {
2170            uint32_t diag_host_type;
2171
2172            buf = (uint8_t *)(clh + 1);
2173            diag_host_type = *(uint32_t *)(buf);
2174#ifdef QC_HAL_DEBUG
2175            ALOGV("diag type = %d", diag_host_type);
2176#endif
2177            buf +=  sizeof(uint32_t); //diag_type
2178            if (diag_host_type == DIAG_TYPE_HOST_EVENTS) {
2179                host_event_hdr_t *event_hdr =
2180                              (host_event_hdr_t *)(buf);
2181#ifdef QC_HAL_DEBUG
2182                ALOGV("diag event_id = %x length %d",
2183                      event_hdr->event_id, event_hdr->length);
2184#endif
2185                buf += sizeof(host_event_hdr_t);
2186                switch (event_hdr->event_id) {
2187                    case EVENT_WLAN_WAKE_LOCK:
2188                        process_wakelock_event(info, buf, event_hdr->length);
2189                        break;
2190                    case EVENT_WLAN_PE:
2191                        process_wlan_pe_event(info, buf, event_hdr->length);
2192                        break;
2193                    case EVENT_WLAN_EAPOL:
2194                        process_wlan_eapol_event(info, buf, event_hdr->length);
2195                        break;
2196                    case EVENT_WLAN_LOG_COMPLETE:
2197                        process_wlan_log_complete_event(info, buf, event_hdr->length);
2198                        break;
2199                    case EVENT_WLAN_LOW_RESOURCE_FAILURE:
2200                        process_wlan_low_resource_failure(info, buf, event_hdr->length);
2201                        break;
2202                    default:
2203                        return WIFI_SUCCESS;
2204                }
2205            } else if (diag_host_type == DIAG_TYPE_HOST_LOG_MSGS) {
2206                drv_msg_t *drv_msg = (drv_msg_t *) (buf);
2207#ifdef QC_HAL_DEBUG
2208                ALOGV("diag event_type = %0x length = %d",
2209                      drv_msg->event_type, drv_msg->length);
2210#endif
2211                if (drv_msg->event_type == WLAN_PKT_LOG_STATS) {
2212                    if ((info->prev_seq_no + 1) !=
2213                            drv_msg->u.pkt_stats_event.msg_seq_no) {
2214                        ALOGE("Few pkt stats messages missed: rcvd = %d, prev = %d",
2215                                drv_msg->u.pkt_stats_event.msg_seq_no,
2216                                info->prev_seq_no);
2217                        if (info->pkt_stats->tx_stats_events) {
2218                            info->pkt_stats->tx_stats_events = 0;
2219                            memset(&info->pkt_stats->tx_stats, 0,
2220                                    sizeof(wifi_ring_per_packet_status_entry));
2221                        }
2222                    }
2223
2224                    info->prev_seq_no =
2225                        drv_msg->u.pkt_stats_event.msg_seq_no;
2226                    status = parse_stats(info,
2227                            drv_msg->u.pkt_stats_event.payload,
2228                            drv_msg->u.pkt_stats_event.payload_len);
2229                    if (status != WIFI_SUCCESS) {
2230                        ALOGE("%s: Failed to parse Tx-Rx stats", __FUNCTION__);
2231                        ALOGE("Received msg Seq_num : %d",
2232                                drv_msg->u.pkt_stats_event.msg_seq_no);
2233                        hexdump((char *)drv_msg->u.pkt_stats_event.payload,
2234                                drv_msg->u.pkt_stats_event.payload_len);
2235                        return status;
2236                    }
2237                }
2238            }
2239        }
2240     } else if (cmd == ANI_NL_MSG_LOG) {
2241         if (!info->cldctx) {
2242             if ((wnl->nlh.nlmsg_len <= sizeof(tAniNlHdr)) ||
2243                 (wnl->nlh.nlmsg_len < (sizeof(tAniNlHdr) + wnl->clh.wmsg.length))) {
2244                 ALOGE("Received LOG message with insufficent length: %d",
2245                       wnl->nlh.nlmsg_len);
2246                 return WIFI_ERROR_UNKNOWN;
2247             }
2248             clh = &wnl->clh;
2249        }
2250        if (clh->wmsg.type == ANI_NL_MSG_LOG_HOST_PRINT_TYPE) {
2251            process_driver_prints(info, (u8 *)(clh + 1), clh->wmsg.length);
2252        } else if (clh->wmsg.type == ANI_NL_MSG_LOG_FW_MSG_TYPE) {
2253            process_firmware_prints(info, (u8 *)(clh + 1), clh->wmsg.length);
2254        }
2255    } else if (cmd == ANI_NL_MSG_CNSS_DIAG) {
2256        uint16_t diag_fw_type;
2257        struct nlmsghdr *nlh = nlmsg_hdr(msg);
2258
2259        if (!info->cldctx) {
2260            buf = (uint8_t *)NLMSG_DATA(wnl) + sizeof(wnl->clh.radio);
2261        } else {
2262            buf = (uint8_t *)&clh->wmsg;
2263        }
2264
2265        fw_event_hdr_t *event_hdr =
2266                          (fw_event_hdr_t *)(buf);
2267        if (!info->cldctx) {
2268            if ((wnl->nlh.nlmsg_len <= NLMSG_HDRLEN + sizeof(fw_event_hdr_t)) ||
2269                (wnl->nlh.nlmsg_len < (NLMSG_HDRLEN + sizeof(fw_event_hdr_t) +
2270                                        event_hdr->length))) {
2271                ALOGE("Received CNSS_DIAG message with insufficent length: %d",
2272                      wnl->nlh.nlmsg_len);
2273                return WIFI_ERROR_UNKNOWN;
2274            }
2275        } else {
2276            if (nlh->nlmsg_len <= NLMSG_HDRLEN + sizeof(dbglog_slot)) {
2277                ALOGE("Received CNSS_DIAG message with insufficent length: %d: %s:%d",
2278                      nlh->nlmsg_len, __FUNCTION__, __LINE__);
2279                return WIFI_ERROR_UNKNOWN;
2280            }
2281        }
2282        diag_fw_type = event_hdr->diag_type;
2283        if (diag_fw_type == DIAG_TYPE_FW_MSG) {
2284            dbglog_slot *slot;
2285            u16 length = 0;
2286
2287            slot = (dbglog_slot *)buf;
2288            if (nlh->nlmsg_len < (NLMSG_HDRLEN + sizeof(dbglog_slot) +
2289                                        slot->length)) {
2290                ALOGE("Received CNSS_DIAG message with insufficent length: %d:"
2291                              " expected: %zu, %s:%d",
2292                      nlh->nlmsg_len,
2293                      (NLMSG_HDRLEN + sizeof(dbglog_slot) +slot->length),
2294                      __FUNCTION__,
2295                      __LINE__);
2296                return WIFI_ERROR_UNKNOWN;
2297            }
2298            length = get_le32((u8 *)&slot->length);
2299            process_fw_diag_msg(info, &slot->payload[0], length);
2300        }
2301    }
2302    return WIFI_SUCCESS;
2303}
2304