/*
 * Copyright (C) 2018 Synaptics Incorporated. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND
 * SYNAPTICS EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES,
 * INCLUDING ANY IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE, AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY
 * INTELLECTUAL PROPERTY RIGHTS. IN NO EVENT SHALL SYNAPTICS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, PUNITIVE, OR
 * CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION WITH THE USE
 * OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED AND
 * BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF
 * COMPETENT JURISDICTION DOES NOT PERMIT THE DISCLAIMER OF DIRECT
 * DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' TOTAL CUMULATIVE LIABILITY
 * TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. DOLLARS.
 */
#include "diag_common.h"
#include "usb_typedefs.h"
#include "hw.h"
#include "string.h"

#define DBUFF_SIZE	(1024*1024)

int dbuff_wr_count;
int dbuff_rd_count;
static char *dbuff = NULL;
static unsigned int usb2_dbg_out = 0;

extern void * USB_memalloc(unsigned int n);

void usb2_set_dbg_mode(unsigned int mode)
{
    usb2_dbg_out = mode;

}

void dbg_disp(char *s)
{
#if PLATFORM==FPGA
	dbg_out(s);
#else
	dbg_printf(PRN_INFO | PRN_BUFFERED,s);
#endif
}

void dbg_dbuff_init()
{
	if (!dbuff){
		dbuff = (char *)USB_memalloc( DBUFF_SIZE );
		dbuff_wr_count = 0;
		dbuff_rd_count = 0;
	}
}

void dbg_out( char *s )
{
	int len;

    dbg_printf(PRN_INFO | PRN_BUFFERED, "%s", s);

	if (!usb2_dbg_out)
		return;

	dbg_dbuff_init();

	len = strlen(s);
	if ((dbuff_wr_count+len)<(DBUFF_SIZE-1)){
		memcpy(dbuff+dbuff_wr_count,s, len);
		dbuff_wr_count += len;
		dbuff[dbuff_wr_count]=0;
	}
}

void dbg_display()
{
	while (dbuff_rd_count < dbuff_wr_count){
		int len;
		char _s[80];

		len = min(dbuff_wr_count-dbuff_rd_count, 64);
		memcpy(_s,dbuff+dbuff_rd_count,len);
		_s[len]=0;
		dbg_printf(PRN_RES, _s );
		dbuff_rd_count += len;
	}
	dbuff_rd_count = dbuff_wr_count;
}

char hex[16]="0123456789ABCDEF";

#define cat16bit(p,i)	{ *p++=hex[(i>>12)&0x0f]; *p++=hex[(i>>8)&0x0f]; *p++=hex[(i>>4)&0x0f]; *p++=hex[(i)&0x0f];}
#define cat8bit(p,i)	{ *p++=hex[(i>>4)&0x0f]; *p++=hex[(i)&0x0f];}


void dbg_outhex(int n)
{
	char *ps;

    dbg_printf(PRN_INFO | PRN_BUFFERED, "%08x", n);

	if (!usb2_dbg_out)
		return;

	dbg_dbuff_init();

	if ((dbuff_wr_count+5)<DBUFF_SIZE){
		ps = dbuff + dbuff_wr_count;

		cat8bit(ps,((n>>24)&0x0ff));
		cat8bit(ps,((n>>16)&0x0ff));
		cat8bit(ps,((n>>8)&0x0ff));
		cat8bit(ps,(n&0x0ff));

		*ps = 0;

		dbuff_wr_count = (ps-dbuff);
	}
}

void dbg_outb(unsigned char n)
{
	char *ps;

    dbg_printf(PRN_INFO | PRN_BUFFERED, "%02x", n);
	if (!usb2_dbg_out)
		return;


	dbg_dbuff_init();
	ps = dbuff + dbuff_wr_count;
	if ((dbuff_wr_count+2)<DBUFF_SIZE){
		cat8bit(ps,(n&0x0ff));
		*ps = 0;
	}
	dbuff_wr_count = (ps-dbuff);
}

void dbg_outw(unsigned int n)
{
	char *ps;

    dbg_printf(PRN_INFO | PRN_BUFFERED, "%04x", n);

	if (!usb2_dbg_out)
		return;

	dbg_dbuff_init();
	ps = dbuff + dbuff_wr_count;

	if ((dbuff_wr_count+3)<DBUFF_SIZE){
		cat8bit(ps,((n>>8)&0x0ff));
		cat8bit(ps,(n&0x0ff));
	}
	*ps = 0;

	dbuff_wr_count = (ps-dbuff);
}

void dbg_outdw(unsigned int n)
{
	char *ps;

    dbg_printf(PRN_INFO | PRN_BUFFERED, "%08x", n);
	if (!usb2_dbg_out)
		return;

	dbg_dbuff_init();
	ps = dbuff + dbuff_wr_count;

	if ((dbuff_wr_count+5)<DBUFF_SIZE){
		cat8bit(ps,((n>>24)&0x0ff));
		cat8bit(ps,((n>>16)&0x0ff));
		cat8bit(ps,((n>>8)&0x0ff));
		cat8bit(ps,(n&0x0ff));
	}
	*ps = 0;

	dbuff_wr_count = (ps-dbuff);
}

void dbg_dump_buffer(unsigned char *b, int len)
{
	int i;
	char *ps;

	for(i=0;i<len;i++){
		if (!(i%8)){
            dbg_printf(PRN_INFO | PRN_BUFFERED, "\n%04x", i);
		}
        dbg_printf(PRN_INFO | PRN_BUFFERED, " %02x", b[i]);
	}

    dbg_printf(PRN_INFO | PRN_BUFFERED, "\n");


    if (!usb2_dbg_out)
		return;


	dbg_dbuff_init();

	ps = dbuff + dbuff_wr_count;
	if (dbuff_wr_count>=(DBUFF_SIZE-len))
		return;

	for(i=0;i<len;i++){

		if (!(i%8)){
			*ps++=0xD;
			*ps++=0x0A;
			cat16bit(ps,i);
		}
		*ps++ = ' ';
		cat8bit( ps, b[i]);
	}
	*ps++=0xD;
	*ps++=0x0A;
	*ps = 0;
	dbuff_wr_count = (ps-dbuff);
}

void dbg_dump_buffer_long(unsigned long *b, int len)
{
	int i;
	for(i=0;i<len;i++){
		if (!(i%4)) dbg_printf(PRN_RES,"\n[%04x]:",i*4);
		dbg_printf(PRN_RES," %08lx",b[i]);
	}
	dbg_printf(PRN_RES,"\n");
}

