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