/*
 * Broadcom Dongle Host Driver (DHD)
 *
 * Copyright (C) 1999-2018, Broadcom.
 *
 *      Unless you and Broadcom execute a separate written software license
 * agreement governing use of this software, this software is licensed to you
 * under the terms of the GNU General Public License version 2 (the "GPL"),
 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
 * following added to such license:
 *
 *      As a special exception, the copyright holders of this software give you
 * permission to link this software with independent modules, and to copy and
 * distribute the resulting executable under terms of your choice, provided that
 * you also meet, for each linked independent module, the terms and conditions of
 * the license of that module.  An independent module is a module which is not
 * derived from this software.  The special exception does not apply to any
 * modifications of the software.
 *
 *      Notwithstanding the above, under no circumstances may you combine this
 * software in any way with any other Broadcom software provided under a license
 * other than the GPL, without Broadcom's express prior written consent.
 *
 * $Id: dhd_csi.c 606280 2015-12-15 05:28:25Z $
 */
#include <osl.h>

#include <bcmutils.h>

#include <bcmendian.h>
#include <linuxver.h>
#include <linux/list.h>
#include <linux/sort.h>
#include <dngl_stats.h>
#include <wlioctl.h>

#include <bcmevent.h>
#include <dhd.h>
#include <dhd_dbg.h>
#include <dhd_csi.h>

#define NULL_CHECK(p, s, err)  \
	do { \
		if (!(p)) { \
			printf("NULL POINTER (%s) : %s\n", __FUNCTION__, (s)); \
			err = BCME_ERROR; \
			return err; \
		} \
	} while (0)

#define TIMESPEC_TO_US(ts)  (((uint64)(ts).tv_sec * USEC_PER_SEC) + \
						(ts).tv_nsec / NSEC_PER_USEC)

#define NULL_ADDR	"\x00\x00\x00\x00\x00\x00"

int
dhd_csi_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data)
{
	int ret = BCME_OK;
	bool is_new = TRUE;
	cfr_dump_data_t *p_event;
	cfr_dump_list_t *ptr, *next, *new;

	NULL_CHECK(dhd, "dhd is NULL", ret);

	DHD_TRACE(("Enter %s\n", __FUNCTION__));

	if (!event_data) {
		DHD_ERROR(("%s: event_data is NULL\n", __FUNCTION__));
		return -EINVAL;
	}
	p_event = (cfr_dump_data_t *)event_data;

	/* check if this addr exist */
	if (!list_empty(&dhd->csi_list)) {
		list_for_each_entry_safe(ptr, next, &dhd->csi_list, list) {
			if (bcmp(&ptr->entry.header.peer_macaddr, &p_event->header.peer_macaddr,
					ETHER_ADDR_LEN) == 0) {
				int pos = 0, dump_len = 0, remain = 0;
				is_new = FALSE;
				DHD_INFO(("CSI data exist\n"));
				if (p_event->header.status == 0) {
					bcopy(&p_event->header, &ptr->entry.header, sizeof(cfr_dump_header_t));
					dump_len = p_event->header.cfr_dump_length;
					if (dump_len < MAX_EVENT_SIZE) {
						bcopy(&p_event->data, &ptr->entry.data, dump_len);
					} else { 
						/* for big csi data */
						uint8 *p = (uint8 *)&ptr->entry.data;
						remain = p_event->header.remain_length;
						if (remain) {
							pos = dump_len - remain - MAX_EVENT_SIZE;
							p += pos;
							bcopy(&p_event->data, p, MAX_EVENT_SIZE);
						}
						/* copy rest of csi data */
						else {
							pos = dump_len - (dump_len % MAX_EVENT_SIZE);
							p += pos;
							bcopy(&p_event->data, p, (dump_len % MAX_EVENT_SIZE));
						}
					}
					return BCME_OK;
				}
			}
		}
	}
	if (is_new) {
		if (dhd->csi_count < MAX_CSI_NUM) {
			new = (cfr_dump_list_t *)MALLOCZ(dhd->osh, sizeof(cfr_dump_list_t));
			if (!new){
				DHD_ERROR(("Malloc cfr dump list error\n"));
				return BCME_NOMEM;
			}
			bcopy(&p_event->header, &new->entry.header, sizeof(cfr_dump_header_t));
			DHD_INFO(("New entry data size %d\n", p_event->header.cfr_dump_length));
			/* for big csi data */
			if (p_event->header.remain_length) {
				DHD_TRACE(("remain %d\n", p_event->header.remain_length));
				bcopy(&p_event->data, &new->entry.data, MAX_EVENT_SIZE);
			}
			else
				bcopy(&p_event->data, &new->entry.data, p_event->header.cfr_dump_length);
			INIT_LIST_HEAD(&(new->list));
			list_add_tail(&(new->list), &dhd->csi_list);
			dhd->csi_count++;
		}
		else {
			DHD_TRACE(("Over maximum CSI Number 8. SKIP it.\n"));
		}
	}
	return ret;
}

int
dhd_csi_init(dhd_pub_t *dhd)
{
	int err = BCME_OK;

	NULL_CHECK(dhd, "dhd is NULL", err);
	INIT_LIST_HEAD(&dhd->csi_list);
	dhd->csi_count = 0;

	return err;
}

int
dhd_csi_deinit(dhd_pub_t *dhd)
{
	int err = BCME_OK;
	cfr_dump_list_t *ptr, *next;

	NULL_CHECK(dhd, "dhd is NULL", err);

	if (!list_empty(&dhd->csi_list)) {
		list_for_each_entry_safe(ptr, next, &dhd->csi_list, list) {
			list_del(&ptr->list);
			MFREE(dhd->osh, ptr, sizeof(cfr_dump_list_t));
		}
	}
	return err;
}

void
dhd_csi_clean_list(dhd_pub_t *dhd)
{
	cfr_dump_list_t *ptr, *next;
	int num = 0;

	if (!dhd) {
		DHD_ERROR(("NULL POINTER: %s\n", __FUNCTION__));
		return;
	}

	if (!list_empty(&dhd->csi_list)) {
		list_for_each_entry_safe(ptr, next, &dhd->csi_list, list) {
			if (0 == ptr->entry.header.remain_length) {
				list_del(&ptr->list);
				num++;
				MFREE(dhd->osh, ptr, sizeof(cfr_dump_list_t));
			}
		}
	}
	dhd->csi_count = 0;
	DHD_TRACE(("Clean up %d record\n", num));
}

int
dhd_csi_dump_list(dhd_pub_t *dhd, char *buf)
{
	int ret = BCME_OK;
	cfr_dump_list_t *ptr, *next;
	uint8 * pbuf = buf;
	int num = 0;
	int length = 0;

	NULL_CHECK(dhd, "dhd is NULL", ret);

	/* check if this addr exist */
	if (!list_empty(&dhd->csi_list)) {
		list_for_each_entry_safe(ptr, next, &dhd->csi_list, list) {
			if (ptr->entry.header.remain_length) {
				DHD_ERROR(("data not ready %d\n", ptr->entry.header.remain_length));
				continue;
			}
			bcopy(&ptr->entry.header, pbuf, sizeof(cfr_dump_header_t));
			length += sizeof(cfr_dump_header_t);
			pbuf += sizeof(cfr_dump_header_t);
			DHD_TRACE(("Copy data size %d\n", ptr->entry.header.cfr_dump_length));
			bcopy(&ptr->entry.data, pbuf, ptr->entry.header.cfr_dump_length);
			length += ptr->entry.header.cfr_dump_length;
			pbuf += ptr->entry.header.cfr_dump_length;
			num++;
		}
	}
	DHD_TRACE(("dump %d record %d bytes\n", num, length));

	return length;
}

