/*****************************************************************************
 Copyright(c) 2010 DTS INSIGHT CORPORATION
 Note:

 Modification history
 +-------------- Historical number (000 to 999)
 |    +--------- Modified System Version
 |    |     +--- Classification of New, Modify, Append, Delete
 v    v     v
 No  Ver  Class Date                Description
 ---+-----+----+------------+--------------------------------------------------
 000 01.00 New  2012/10/01      New
 001 02.00 CHG  2014/01/06      Fixed #13339
 002 02.12 MOD  2014/12/12      Fixed #13672
                                #13699
 003 03.00 MOD  2015/05/12      Supported #13749

*****************************************************************************/
#define __SMTPRINTF_C__

/* Include specification ****************************************************/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include "SMTDef.h"
#include "SMTAPI.h"
#include "SMTUser.h"
#include "smtif.h"
#include "SMTAPI_CP.h"

/* Function prototypes ******************************************************/
int  SMT_Putw(int level,const char *s);

/* static Function prototypes ******************************************************/
static _SMT_UNSIGNED_32BIT_INTEGER smt_strlen(const char *s);

/* External variables *******************************************************/
extern int smt_fd;

/****************************************************************************
1.Function: equivalent to printf function. use vsprintf

2.Restriction, Cautions:
Recommend _SMT_Puts() function if complicated format don't use

3.Argument
I/O|Variable Name			   |Explanation
---+---------------------------+---------------------------------------------
I/	level						Level of debug print output
I/	*format						Pointer for character string to specify the syntax
I/	arg							Output data in accordance with the syntax


4.Return Value:
	_SMT_OK:Normal end / _SMT_NG:Unuseal end
*****************************************************************************/
int _SMT_Printf(int level,const char *format , ... )
{
	va_list	ap;
	char s[_SMT_STR_MAX_SIZE_B] __attribute__ ((aligned (4)));

	if( smt_fd<0 ){
		if( _SMT_Open() != _SMT_OK ) return( _SMT_NG );
	}
	if ( _SMT_GetDebugLevel() & (1 <<(_SMT_UNSIGNED_32BIT_INTEGER)level) ){
		return( _SMT_OK );
	}
	va_start(ap,format);
	vsnprintf(s,_SMT_STR_MAX_SIZE_B,format,ap);
	va_end(ap);
	return( SMT_Putw(level,s) );
}

/****************************************************************************
1.Function: Output String

2.Restriction, Cautions:

3.Argument
I/O|Variable Name			   |Explanation
---+---------------------------+---------------------------------------------
I/	level						Level of debug print output
I/	*s							Pointer for character string to output

4.Return Value:
	_SMT_OK:Normal end / _SMT_NG:Unuseal end
*****************************************************************************/
int _SMT_Puts(int level,const char *s)
{

	if( smt_fd<0 ){
		if( _SMT_Open() != _SMT_OK ) return( _SMT_NG );
	}
	if ( _SMT_GetDebugLevel() & (1 <<(_SMT_UNSIGNED_32BIT_INTEGER)level) ){
		return( _SMT_OK );
	}
	return( SMT_Putw(level,s) );
}

/*****************************************************************************
1.Function: Output one word to SMT_port

2.Restriction, Cautions:string length is 1WORD(4BYTE)

3.Argument
I/O|Variable Name			   |Explanation
---+---------------------------+---------------------------------------------
I/	level						Level of debug print output
I/	*s							Pointer for character string to output

4.Return Value:
	_SMT_OK:Normal end / _SMT_NG:Unuseal end
*****************************************************************************/
int SMT_Putw(int level,const char *s)
{
	_SMT_UNSIGNED_32BIT_INTEGER data;
	int status;
	_SMT_UNSIGNED_32BIT_INTEGER i = 0;
	_SMT_UNSIGNED_32BIT_INTEGER len;
	_SMT_UNSIGNED_32BIT_INTEGER size_word = 0;
	_SMT_UNSIGNED_32BIT_INTEGER pos = 0;
	_SMT_UNSIGNED_32BIT_INTEGER out[_SMT_STR_MAX_SIZE_B/sizeof(_SMT_UNSIGNED_32BIT_INTEGER)] __attribute__ ((aligned (4)));

	len = smt_strlen((char *)s);
	size_word = (len + sizeof(_SMT_UNSIGNED_32BIT_INTEGER)) / (sizeof(_SMT_UNSIGNED_32BIT_INTEGER));
	size_word = ((len % 4) == 0) ? size_word - 1 : size_word;
	out[pos]  = _SMT_ATR_PRINT | ((size_word) << _SMT_OUT_SIZE_POS) | ((level & _SMT_DBG_LV_MSK) << _SMT_DBG_LV_POS);
	pos++;

	for(i=0;i<size_word;i++){
		data = 0x00000000UL;
		switch (len - (i * 4)) {
		case 1:
			data  = *s++;
			break ;
		case 2:
			data  = *s++;
			data += *s++ << 8;
			break ;
		case 3:
			data  = *s++;
			data += *s++ << 8;
			data += *s++ << 16;
			break ;
		default:
			data  = *s++;
			data += *s++ << 8;
			data += *s++ << 16;
			data += *s++ << 24;
			break ;
		}
		out[pos] = data;
		pos++;
	}
	status = write(smt_fd, out, pos);
	if( status<0 ){
		return( _SMT_NG );
	}
	return( _SMT_OK );
}

/*****************************************************************************
1.Function: Count number of characters

2.Restriction, Cautions: max string length is 124

3.Argument
I/O|Variable Name			   |Explanation
---+---------------------------+---------------------------------------------
I/	*s							Pointer for character string to output

4.Return Value:
	string length

*****************************************************************************/
static _SMT_UNSIGNED_32BIT_INTEGER smt_strlen(const char *s)
{
	_SMT_UNSIGNED_32BIT_INTEGER i=0;

	while (s[i] != '\0') {
		i++;
		if( i >= _SMT_STR_MAX_SIZE_B ){
			break;
		}
	}
	if( i>_SMT_STR_MAX_SIZE_B ){
		i = _SMT_STR_MAX_SIZE_B;
	}
	return(i);
}

/****************************************************************************
1.Function: equivalent to printf function

2.Restriction, Cautions:

3.Argument
I/O|Variable Name			   |Explanation
---+---------------------------+---------------------------------------------

4.Return Value:

*****************************************************************************/
int _SMT_CP_Printf(int level,const char *format , ... )
{
	va_list	ap;
	char s[_SMT_STR_MAX_SIZE_B] __attribute__ ((aligned (4)));

	if( smt_fd<0 ){
		if( _SMT_Open() != _SMT_OK ) return( _SMT_NG );
	}
	if ( _SMT_GetDebugLevel() & (1 <<(_SMT_UNSIGNED_32BIT_INTEGER)level) ){
		return( _SMT_OK );
	}
	va_start(ap,format);
	vsnprintf(s,_SMT_STR_MAX_SIZE_B,format,ap);
	va_end(ap);
	return( SMT_Putw(level,s) );
	
}