/************************************************************************
 Debug macro translation.

Copyright (C) 1997-2017 AudioScience, Inc. All rights reserved.

This software is provided 'as-is', without any express or implied warranty.
In no event will AudioScience Inc. be held liable for any damages arising
from the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented; you must not
   claim that you wrote the original software. If you use this software
   in a product, an acknowledgment in the product documentation would be
   appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.
3. This copyright notice and list of conditions may not be altered or removed
   from any source distribution.

AudioScience, Inc. <support@audioscience.com>

( This license is GPL compatible see http://www.gnu.org/licenses/license-list.html#GPLCompatibleLicenses )

************************************************************************/

#include "hpi_internal.h"
#include "hpidebug.h"

/* Debug level; 0 quiet; 1 informative, 2 debug, 3 verbose debug.  */
#ifdef HPI_BUILD_NO_SHARED_GLOBALS
#warning hpiDebugLevel is shared between all driver instances
#endif // HPI_BUILD_NO_SHARED_GLOBALS
int hpiDebugLevel = HPI_DEBUG_LEVEL_DEFAULT;
#ifndef HPI_OS_LINUX_KERNEL
int hpiDebugHaltOnFatal = 0;
static const DBG_CHAR *idx_out_of_bounds_str = DBG_TEXT("INDEX OUT OF BOUNDS");
#endif

void HPI_DebugInit(void)
{
#ifdef SGT_SERIAL_LOGGING
	HpiDebug_SerialLog_Init();	//SGT
#endif
	HPIOS_DEBUG_PRINTF(HPI_DEBUG_FLAG_INFO DBG_TEXT("Debug Start\n"));
}

int HPI_DebugLevelSet(int level)
{
	int old_level;

	old_level = hpiDebugLevel;
	hpiDebugLevel = level;
	return old_level;
}

int HPI_DebugLevelGet(void)
{
	return hpiDebugLevel;
}

#ifndef HPI_OS_LINUX_KERNEL

int HPI_DebugSetHaltOnFatal(int onoff)
{
	int old_val;

	old_val = hpiDebugHaltOnFatal;
	hpiDebugHaltOnFatal = onoff;
	return old_val;
}

#ifdef HPIOS_DEBUG_PRINT
/* implies OS has no printf-like function */
#include <stdarg.h>

void hpi_debug_printf(DBG_CHAR * fmt, ...)
{
	va_list arglist;
	DBG_CHAR buffer[256];

	va_start(arglist, fmt);
	HPIOS_VSPRINTF(buffer, 255, fmt, arglist);

	if (buffer[0])
		HPIOS_DEBUG_PRINT(buffer);
	va_end(arglist);
}
#endif
#endif

#ifndef HPI_OS_LINUX_KERNEL
/* struct treenode is used to handle sparse arrays of debug strings */
struct treenode {
	const void *array;
	int numElements;
};

#define get_treenode_elem(node_ptr, idx, type, default_val)  \
	((idx >= 0 && idx < (node_ptr)->numElements)?&(*((type *)(node_ptr)->array)[idx]):(type)default_val)

#define treenode_from_strings(nodename, array) \
static const DBG_CHAR * const nodename##_array[] = array; \
static struct treenode nodename = { \
	&nodename##_array, \
	ARRAY_SIZE(nodename##_array) \
}

#define treenode_from_nodes(nodename, array) \
static struct treenode *nodename##_array[] = array; \
static struct treenode nodename = { \
	&nodename##_array, \
	ARRAY_SIZE(nodename##_array) \
}

treenode_from_strings(hpi_control_type_strings, HPI_CONTROL_TYPE_STRINGS);

#define HPI_NODE_STRINGS {DBG_TEXT("NODE is invalid object")}

treenode_from_strings(hpi_subsys_strings, HPI_SUBSYS_STRINGS);
treenode_from_strings(hpi_adapter_strings, HPI_ADAPTER_STRINGS);
treenode_from_strings(hpi_istream_strings, HPI_ISTREAM_STRINGS);
treenode_from_strings(hpi_ostream_strings, HPI_OSTREAM_STRINGS);
treenode_from_strings(hpi_mixer_strings, HPI_MIXER_STRINGS);
treenode_from_strings(hpi_node_strings, HPI_NODE_STRINGS);
treenode_from_strings(hpi_control_strings, HPI_CONTROL_STRINGS);
treenode_from_strings(hpi_nvmemory_strings, HPI_NVMEMORY_STRINGS);
treenode_from_strings(hpi_digitalio_strings, HPI_DIGITALIO_STRINGS);
treenode_from_strings(hpi_watchdog_strings, HPI_WATCHDOG_STRINGS);
treenode_from_strings(hpi_clock_strings, HPI_CLOCK_STRINGS);
treenode_from_strings(hpi_profile_strings, HPI_PROFILE_STRINGS);
treenode_from_strings(hpi_asyncevent_strings, HPI_ASYNCEVENT_STRINGS);
#define HPI_FUNCTION_STRING_NODES \
{ \
  &hpi_subsys_strings,\
  &hpi_adapter_strings,\
  &hpi_ostream_strings,\
  &hpi_istream_strings,\
  &hpi_mixer_strings,\
  &hpi_node_strings,\
  &hpi_control_strings,\
  &hpi_nvmemory_strings,\
  &hpi_digitalio_strings,\
  &hpi_watchdog_strings,\
  &hpi_clock_strings,\
  &hpi_profile_strings,\
  &hpi_control_strings, \
  &hpi_asyncevent_strings \
}
treenode_from_nodes(hpi_function_string_nodes, HPI_FUNCTION_STRING_NODES);

compile_time_assert(HPI_OBJ_MAXINDEX == 14, obj_list_doesnt_match);

/**
   Use COG <http://nedbatchelder.com/code/cog/index.html> to parse hpi_internal.h and build
   a control attribute's name table.
*/
/*[[[cog
import cog
import re

def parse_error_define(inc_file, line):
        tokens = re.split(r'\s+|[=(),]+', line)
        tokens = [t for t in tokens if t]
        # We expect tokens to be as follows:
        # [define,'HPI6000_ERROR_...', value]
        if len(tokens) >= 3:
            return int(tokens[2]), tokens[1]
        else:
            print('Malformed line? :%s'%line)
            return None

def parse_error_defines(inc_file, backend_name):
    error_defines = []
    while True:
        line = inc_file.readline()
        if not line:
            break
        # Look for attribute lines
        if line.find(backend_name + '_ERROR_') > 0  and  line[0] == '#':
            res = parse_error_define(inc_file, line[1:])
            if res == None:
                continue
            error_defines.append(res)
    return error_defines

def parse_control_attribute_define(inc_file, line):
        tokens = re.split(r'\s+|[=(),]+', line)
        tokens = [t for t in tokens if t]
        # We expect tokens to be as follows:
        # [CONTROL_ATTRIBUTE_DEFINE,'HPI_CTL_ATTR', CONTROL_NAME, ATTR_IDX]
        assert tokens[1] == 'HPI_CTL_ATTR'
        if len(tokens) > 3:
            return tokens[0], tokens[2], tokens[3]
        else:
            print('Malformed line? :%s'%line)
            return None

def parse_control_attributes_info(inc_file):
    per_control_attributes = {}
    while True:
        line = inc_file.readline()
        if not line:
            break
        # Look for attribute lines
        if line.find('HPI_CTL_ATTR(') > 0  and  line[0] != '#':
                res = parse_control_attribute_define(inc_file, line)
                if res == None:
                    continue
                ctrl_attr_define, ctrl_name, attr_idx = res
                ctrl_define = 'HPI_CONTROL_' + ctrl_name
                attr_name_prefix = 'HPI_%s_' % ctrl_name
                ctrl_attr_name = ctrl_attr_define[len(attr_name_prefix):]
                attributes = per_control_attributes.get(ctrl_define, [])
                attributes.append((int(attr_idx), ctrl_attr_name))
                per_control_attributes[ctrl_define] = attributes
    return per_control_attributes

def write_preamble():
    cog.out('/'+'*'+'*'*78+'\n')
    cog.out("""
Debug string arrays automatically generated from hpi_internal.h, hpi6000.c, hpi6205.c. Do not edit, instead
run 'cog -c -r [thisfile]' to update it.
""")
    cog.out('*'*78+'*'+'/\n')
    cog.out('\n\n')

def write_control_attribute_table(ctrl_define, attrs):
    skip_len = len('HPI_CONTROL_')
    ctrl_name = ctrl_define[skip_len:]
    table_define_identifier = 'HPI_CONTROL_%s_ATTR_NAME_STRINGS' % ctrl_name.upper()
    table_var_identifier = 'hpi_ctrl_%s_attr_name_strings' % ctrl_name.lower()
    cog.out('/' + '* A table for control %s attributes name lookup *' % ctrl_name.lower() + '/\n')
    cog.out('#define %s {\\' % table_define_identifier +'\n')
    # Build an attribute dictionary keyed by index
    attr_dict = dict(attrs)
    # Total row count will be max index + 1
    count = max(attr_dict.keys())+1
    # Sort the attribute list by ascending index
    for idx in xrange(count):
        if attr_dict.has_key(idx):
            cog.out('DBG_TEXT("%s"),\\\n' % (attr_dict[idx].upper()))
        else:
            cog.out('DBG_TEXT("INVALID ATTR INDEX %d"),\\\n' % idx)
    cog.out('}' + '\n')
    cog.out('treenode_from_strings(%s, %s);' % (table_var_identifier, table_define_identifier) + '\n')
    cog.out('/'+ ('* Total items in table: %d *' % count) +'/\n')
    cog.out('\n')

def write_error_str_table(errors, backend_name):
    skip_len = len('HPI6000_ERROR_')
    table_define_identifier = backend_name.upper() + '_ERROR_NAME_STRINGS'
    table_var_identifier = backend_name +'_error_name_strings'
    # Build an attribute dictionary keyed by index
    attr_dict = dict(errors)
    # Total row count will be max index + 1
    first = min(attr_dict.keys())
    last = max(attr_dict.keys())
    count = last - first + 1
    cog.out('#ifdef HPI_BUILD_INCLUDE_%s' % backend_name.upper() + '\n')
    cog.out('#define %s %d' % (attr_dict[first], first) +'\n')
    cog.out('/' + '* A table for %s error string lookup *' % backend_name + '/\n')
    cog.out('#define %s {\\' % table_define_identifier +'\n')
    # Sort the attribute list by ascending index
    for idx in xrange(first, last+1):
        if attr_dict.has_key(idx):
            error_name = attr_dict[idx][skip_len:]
            cog.out('DBG_TEXT("%s"),\\\n' % (error_name.upper()))
        else:
            cog.out('DBG_TEXT("INVALID ERROR INDEX %d"),\\\n' % idx)
    cog.out('}' + '\n')
    cog.out('treenode_from_strings(%s, %s);' % (table_var_identifier, table_define_identifier) + '\n')
    cog.out('/'+ ('* Total items in table: %d *' % count) +'/\n')
    cog.out('#endif // ifdef HPI_BUILD_INCLUDE_%s' % backend_name.upper() + '\n')
    cog.out('\n')

def gen_control_attributes_dbg_tables():
    inc_file = open('hpi_internal.h','rt')
    control_attributes = parse_control_attributes_info(inc_file)
    inc_file.close()
    # Output generated code
    for control, attrs in control_attributes.items():
        write_control_attribute_table(control, attrs)

write_preamble()
gen_control_attributes_dbg_tables()
]]]*/
/*******************************************************************************

Debug string arrays automatically generated from hpi_internal.h, hpi6000.c, hpi6205.c. Do not edit, instead
run 'cog -c -r [thisfile]' to update it.
*******************************************************************************/


/* A table for control meter attributes name lookup */
#define HPI_CONTROL_METER_ATTR_NAME_STRINGS {\
DBG_TEXT("INVALID ATTR INDEX 0"),\
DBG_TEXT("RMS"),\
DBG_TEXT("PEAK"),\
DBG_TEXT("RMS_BALLISTICS"),\
DBG_TEXT("PEAK_BALLISTICS"),\
DBG_TEXT("NUM_CHANNELS"),\
}
treenode_from_strings(hpi_ctrl_meter_attr_name_strings, HPI_CONTROL_METER_ATTR_NAME_STRINGS);
/* Total items in table: 6 */

/* A table for control level attributes name lookup */
#define HPI_CONTROL_LEVEL_ATTR_NAME_STRINGS {\
DBG_TEXT("INVALID ATTR INDEX 0"),\
DBG_TEXT("GAIN"),\
DBG_TEXT("INVALID ATTR INDEX 2"),\
DBG_TEXT("INVALID ATTR INDEX 3"),\
DBG_TEXT("INVALID ATTR INDEX 4"),\
DBG_TEXT("INVALID ATTR INDEX 5"),\
DBG_TEXT("INVALID ATTR INDEX 6"),\
DBG_TEXT("INVALID ATTR INDEX 7"),\
DBG_TEXT("INVALID ATTR INDEX 8"),\
DBG_TEXT("INVALID ATTR INDEX 9"),\
DBG_TEXT("RANGE"),\
}
treenode_from_strings(hpi_ctrl_level_attr_name_strings, HPI_CONTROL_LEVEL_ATTR_NAME_STRINGS);
/* Total items in table: 11 */

/* A table for control compander attributes name lookup */
#define HPI_CONTROL_COMPANDER_ATTR_NAME_STRINGS {\
DBG_TEXT("INVALID ATTR INDEX 0"),\
DBG_TEXT("PARAMS"),\
DBG_TEXT("MAKEUPGAIN"),\
DBG_TEXT("THRESHOLD"),\
DBG_TEXT("RATIO"),\
DBG_TEXT("ATTACK"),\
DBG_TEXT("DECAY"),\
}
treenode_from_strings(hpi_ctrl_compander_attr_name_strings, HPI_CONTROL_COMPANDER_ATTR_NAME_STRINGS);
/* Total items in table: 7 */

/* A table for control cobranet attributes name lookup */
#define HPI_CONTROL_COBRANET_ATTR_NAME_STRINGS {\
DBG_TEXT("INVALID ATTR INDEX 0"),\
DBG_TEXT("SET"),\
DBG_TEXT("GET"),\
DBG_TEXT("T_SET_DATA"),\
DBG_TEXT("T_GET_DATA"),\
DBG_TEXT("GET_STATUS"),\
DBG_TEXT("SEND_PACKET"),\
DBG_TEXT("GET_PACKET"),\
}
treenode_from_strings(hpi_ctrl_cobranet_attr_name_strings, HPI_CONTROL_COBRANET_ATTR_NAME_STRINGS);
/* Total items in table: 8 */

/* A table for control bitstream attributes name lookup */
#define HPI_CONTROL_BITSTREAM_ATTR_NAME_STRINGS {\
DBG_TEXT("INVALID ATTR INDEX 0"),\
DBG_TEXT("DATA_POLARITY"),\
DBG_TEXT("CLOCK_EDGE"),\
DBG_TEXT("CLOCK_SOURCE"),\
DBG_TEXT("ACTIVITY"),\
}
treenode_from_strings(hpi_ctrl_bitstream_attr_name_strings, HPI_CONTROL_BITSTREAM_ATTR_NAME_STRINGS);
/* Total items in table: 5 */

/* A table for control aesebutx attributes name lookup */
#define HPI_CONTROL_AESEBUTX_ATTR_NAME_STRINGS {\
DBG_TEXT("INVALID ATTR INDEX 0"),\
DBG_TEXT("FORMAT"),\
DBG_TEXT("INVALID ATTR INDEX 2"),\
DBG_TEXT("SAMPLERATE"),\
DBG_TEXT("CHANNELSTATUS"),\
DBG_TEXT("USERDATA"),\
}
treenode_from_strings(hpi_ctrl_aesebutx_attr_name_strings, HPI_CONTROL_AESEBUTX_ATTR_NAME_STRINGS);
/* Total items in table: 6 */

/* A table for control aeseburx attributes name lookup */
#define HPI_CONTROL_AESEBURX_ATTR_NAME_STRINGS {\
DBG_TEXT("INVALID ATTR INDEX 0"),\
DBG_TEXT("FORMAT"),\
DBG_TEXT("ERRORSTATUS"),\
DBG_TEXT("SAMPLERATE"),\
DBG_TEXT("CHANNELSTATUS"),\
DBG_TEXT("USERDATA"),\
}
treenode_from_strings(hpi_ctrl_aeseburx_attr_name_strings, HPI_CONTROL_AESEBURX_ATTR_NAME_STRINGS);
/* Total items in table: 6 */

/* A table for control volume attributes name lookup */
#define HPI_CONTROL_VOLUME_ATTR_NAME_STRINGS {\
DBG_TEXT("INVALID ATTR INDEX 0"),\
DBG_TEXT("GAIN"),\
DBG_TEXT("AUTOFADE"),\
DBG_TEXT("MUTE"),\
DBG_TEXT("GAIN_AND_FLAGS"),\
DBG_TEXT("INVALID ATTR INDEX 5"),\
DBG_TEXT("NUM_CHANNELS"),\
DBG_TEXT("INVALID ATTR INDEX 7"),\
DBG_TEXT("INVALID ATTR INDEX 8"),\
DBG_TEXT("INVALID ATTR INDEX 9"),\
DBG_TEXT("RANGE"),\
}
treenode_from_strings(hpi_ctrl_volume_attr_name_strings, HPI_CONTROL_VOLUME_ATTR_NAME_STRINGS);
/* Total items in table: 11 */

/* A table for control tuner attributes name lookup */
#define HPI_CONTROL_TUNER_ATTR_NAME_STRINGS {\
DBG_TEXT("INVALID ATTR INDEX 0"),\
DBG_TEXT("BAND"),\
DBG_TEXT("FREQ"),\
DBG_TEXT("LEVEL_AVG"),\
DBG_TEXT("LEVEL_RAW"),\
DBG_TEXT("SNR"),\
DBG_TEXT("GAIN"),\
DBG_TEXT("STATUS"),\
DBG_TEXT("MODE"),\
DBG_TEXT("RDS"),\
DBG_TEXT("DEEMPHASIS"),\
DBG_TEXT("PROGRAM"),\
DBG_TEXT("HDRADIO_SIGNAL_QUALITY"),\
DBG_TEXT("HDRADIO_SDK_VERSION"),\
DBG_TEXT("HDRADIO_DSP_VERSION"),\
DBG_TEXT("HDRADIO_BLEND"),\
DBG_TEXT("DABRADIO_AS"),\
DBG_TEXT("DABRADIO_ASC"),\
DBG_TEXT("DABRADIO_MULTIPLEX_NAME"),\
DBG_TEXT("DABRADIO_MULTIPLEX_ID"),\
DBG_TEXT("DABRADIO_SERVICE_ID"),\
DBG_TEXT("DABRADIO_AUDIO_INFO"),\
DBG_TEXT("DABRADIO_SERVICE_INFO"),\
DBG_TEXT("DABRADIO_COMPONENT_INFO"),\
DBG_TEXT("DABRADIO_SERVICE"),\
DBG_TEXT("DABRADIO_DIGITAL_DATA"),\
DBG_TEXT("BACKGROUND_PROC"),\
DBG_TEXT("DIRECT_MSG"),\
}
treenode_from_strings(hpi_ctrl_tuner_attr_name_strings, HPI_CONTROL_TUNER_ATTR_NAME_STRINGS);
/* Total items in table: 28 */

/* A table for control multiplexer attributes name lookup */
#define HPI_CONTROL_MULTIPLEXER_ATTR_NAME_STRINGS {\
DBG_TEXT("INVALID ATTR INDEX 0"),\
DBG_TEXT("SOURCE"),\
DBG_TEXT("QUERYSOURCE"),\
}
treenode_from_strings(hpi_ctrl_multiplexer_attr_name_strings, HPI_CONTROL_MULTIPLEXER_ATTR_NAME_STRINGS);
/* Total items in table: 3 */

/* A table for control pad attributes name lookup */
#define HPI_CONTROL_PAD_ATTR_NAME_STRINGS {\
DBG_TEXT("INVALID ATTR INDEX 0"),\
DBG_TEXT("CHANNEL_NAME"),\
DBG_TEXT("ARTIST"),\
DBG_TEXT("TITLE"),\
DBG_TEXT("COMMENT"),\
DBG_TEXT("PROGRAM_TYPE"),\
DBG_TEXT("PROGRAM_ID"),\
DBG_TEXT("TA_SUPPORT"),\
DBG_TEXT("TA_ACTIVE"),\
}
treenode_from_strings(hpi_ctrl_pad_attr_name_strings, HPI_CONTROL_PAD_ATTR_NAME_STRINGS);
/* Total items in table: 9 */

/* A table for control microphone attributes name lookup */
#define HPI_CONTROL_MICROPHONE_ATTR_NAME_STRINGS {\
DBG_TEXT("INVALID ATTR INDEX 0"),\
DBG_TEXT("PHANTOM_POWER"),\
}
treenode_from_strings(hpi_ctrl_microphone_attr_name_strings, HPI_CONTROL_MICROPHONE_ATTR_NAME_STRINGS);
/* Total items in table: 2 */

/* A table for control vox attributes name lookup */
#define HPI_CONTROL_VOX_ATTR_NAME_STRINGS {\
DBG_TEXT("INVALID ATTR INDEX 0"),\
DBG_TEXT("THRESHOLD"),\
}
treenode_from_strings(hpi_ctrl_vox_attr_name_strings, HPI_CONTROL_VOX_ATTR_NAME_STRINGS);
/* Total items in table: 2 */

/* A table for control equalizer attributes name lookup */
#define HPI_CONTROL_EQUALIZER_ATTR_NAME_STRINGS {\
DBG_TEXT("INVALID ATTR INDEX 0"),\
DBG_TEXT("NUM_FILTERS"),\
DBG_TEXT("FILTER"),\
DBG_TEXT("COEFFICIENTS"),\
}
treenode_from_strings(hpi_ctrl_equalizer_attr_name_strings, HPI_CONTROL_EQUALIZER_ATTR_NAME_STRINGS);
/* Total items in table: 4 */

/* A table for control universal attributes name lookup */
#define HPI_CONTROL_UNIVERSAL_ATTR_NAME_STRINGS {\
DBG_TEXT("INVALID ATTR INDEX 0"),\
DBG_TEXT("ENTITY"),\
}
treenode_from_strings(hpi_ctrl_universal_attr_name_strings, HPI_CONTROL_UNIVERSAL_ATTR_NAME_STRINGS);
/* Total items in table: 2 */

/* A table for control generic attributes name lookup */
#define HPI_CONTROL_GENERIC_ATTR_NAME_STRINGS {\
DBG_TEXT("INVALID ATTR INDEX 0"),\
DBG_TEXT("ENABLE"),\
DBG_TEXT("EVENT_ENABLE"),\
}
treenode_from_strings(hpi_ctrl_generic_attr_name_strings, HPI_CONTROL_GENERIC_ATTR_NAME_STRINGS);
/* Total items in table: 3 */

/* A table for control silencedetector attributes name lookup */
#define HPI_CONTROL_SILENCEDETECTOR_ATTR_NAME_STRINGS {\
DBG_TEXT("INVALID ATTR INDEX 0"),\
DBG_TEXT("THRESHOLD"),\
DBG_TEXT("STATE"),\
DBG_TEXT("DELAY"),\
}
treenode_from_strings(hpi_ctrl_silencedetector_attr_name_strings, HPI_CONTROL_SILENCEDETECTOR_ATTR_NAME_STRINGS);
/* Total items in table: 4 */

/* A table for control tonedetector attributes name lookup */
#define HPI_CONTROL_TONEDETECTOR_ATTR_NAME_STRINGS {\
DBG_TEXT("INVALID ATTR INDEX 0"),\
DBG_TEXT("THRESHOLD"),\
DBG_TEXT("STATE"),\
DBG_TEXT("FREQUENCY"),\
}
treenode_from_strings(hpi_ctrl_tonedetector_attr_name_strings, HPI_CONTROL_TONEDETECTOR_ATTR_NAME_STRINGS);
/* Total items in table: 4 */

/* A table for control sampleclock attributes name lookup */
#define HPI_CONTROL_SAMPLECLOCK_ATTR_NAME_STRINGS {\
DBG_TEXT("INVALID ATTR INDEX 0"),\
DBG_TEXT("SOURCE"),\
DBG_TEXT("SAMPLERATE"),\
DBG_TEXT("SOURCE_INDEX"),\
DBG_TEXT("LOCAL_SAMPLERATE"),\
DBG_TEXT("AUTO"),\
DBG_TEXT("LOCAL_LOCK"),\
DBG_TEXT("LOCAL_SAMPLERATE_EX"),\
}
treenode_from_strings(hpi_ctrl_sampleclock_attr_name_strings, HPI_CONTROL_SAMPLECLOCK_ATTR_NAME_STRINGS);
/* Total items in table: 8 */

/* A table for control channel_mode attributes name lookup */
#define HPI_CONTROL_CHANNEL_MODE_ATTR_NAME_STRINGS {\
DBG_TEXT("INVALID ATTR INDEX 0"),\
DBG_TEXT("MODE"),\
}
treenode_from_strings(hpi_ctrl_channel_mode_attr_name_strings, HPI_CONTROL_CHANNEL_MODE_ATTR_NAME_STRINGS);
/* Total items in table: 2 */

//[[[end]]]

#define HPI_CONTROL_ATTR_STRING_TABLES \
{ \
	&hpi_ctrl_generic_attr_name_strings, \
	NULL, /*&hpi_ctrl_connection_attr_name_strings,*/ \
	&hpi_ctrl_volume_attr_name_strings, \
	&hpi_ctrl_meter_attr_name_strings, \
	NULL, /*&hpi_ctrl_mute_attr_name_strings,*/ \
	&hpi_ctrl_multiplexer_attr_name_strings, \
	&hpi_ctrl_aesebutx_attr_name_strings, \
	&hpi_ctrl_aeseburx_attr_name_strings, \
	&hpi_ctrl_level_attr_name_strings, \
	&hpi_ctrl_tuner_attr_name_strings, \
	NULL, /*&hpi_ctrl_onoffswitch_attr_name_strings,*/ \
	&hpi_ctrl_vox_attr_name_strings, \
	NULL, /*&hpi_ctrl_aes18_transmitter_attr_name_strings,*/ \
	NULL, /*&hpi_ctrl_aes18_receiver_attr_name_strings,*/ \
	NULL, /*&hpi_ctrl_aes18_blockgenerator_attr_name_strings,*/ \
	&hpi_ctrl_channel_mode_attr_name_strings, \
	&hpi_ctrl_bitstream_attr_name_strings, \
	&hpi_ctrl_sampleclock_attr_name_strings, \
	&hpi_ctrl_microphone_attr_name_strings, \
	&hpi_ctrl_equalizer_attr_name_strings, \
	&hpi_ctrl_compander_attr_name_strings, \
	&hpi_ctrl_cobranet_attr_name_strings, \
	&hpi_ctrl_tonedetector_attr_name_strings, \
	&hpi_ctrl_silencedetector_attr_name_strings, \
	&hpi_ctrl_pad_attr_name_strings, \
	NULL, /*&hpi_ctrl_src_attr_name_strings,*/ \
	&hpi_ctrl_universal_attr_name_strings \
}

compile_time_assert((HPI_CONTROL_LAST_INDEX + 1 == 27),
		    controltype_attrs_match_defs);

treenode_from_nodes(hpi_ctrl_attr_string_tables, HPI_CONTROL_ATTR_STRING_TABLES);


static DBG_CHAR *hpi_function_string(unsigned int function)
{
	int object;
	struct treenode *tmp;

	object = function / HPI_OBJ_FUNCTION_SPACING;
	function = function - object * HPI_OBJ_FUNCTION_SPACING;

	if (object == 0 || object == HPI_OBJ_NODE
	    || object > (int)hpi_function_string_nodes.numElements)
		return DBG_TEXT("Invalid object");

	tmp =
	    get_treenode_elem(&hpi_function_string_nodes, object - 1,
			      struct treenode *, NULL);

	if (function == 0 || !tmp || (int)function > tmp->numElements)
		return DBG_TEXT("Invalid function");

	return get_treenode_elem(tmp, (int)function - 1, DBG_CHAR *, idx_out_of_bounds_str);
}

void hpi_debug_message(HPI_MESSAGE *phm, DBG_CHAR * szFileline)
{
	if (phm) {
		if ((phm->wObject <= HPI_OBJ_MAXINDEX) && phm->wObject) {
			uint16_t wIndex = 0;
			uint16_t wAttrib = 0;
			int isControl = 0;

			wIndex = phm->wObjIndex;
			switch (phm->wObject) {
			case HPI_OBJ_ADAPTER:
			case HPI_OBJ_PROFILE:
				break;
			case HPI_OBJ_MIXER:
				if (phm->wFunction ==
				    HPI_MIXER_GET_CONTROL_BY_INDEX)
					wIndex = phm->u.m.wControlIndex;
				break;
			case HPI_OBJ_OSTREAM:
			case HPI_OBJ_ISTREAM:
				break;

			case HPI_OBJ_NVMEMORY:
				wIndex = phm->u.n.wAddress;
				wAttrib = phm->u.n.wData;
				break;

			case HPI_OBJ_CONTROL:
				if (phm->u.c.wAttribute < 0x100) /* probably an entity size */
					wAttrib = HPI_CTL_ATTR(UNIVERSAL, 1) ;
				else
					wAttrib = phm->u.c.wAttribute;
				isControl =1;
				break;
			default:
				break;
			}

			if (isControl && (wAttrib & 0xFF00)) {
				int controlType = (wAttrib & 0xFF00) >> 8;
				int attrIndex = HPI_CTL_ATTR_INDEX(wAttrib);
				/* note the KERN facility level
				    is in szFileline already */
				struct treenode *attr_str_table_ptr = \
					get_treenode_elem(&hpi_ctrl_attr_string_tables, controlType, struct treenode *, NULL);
				// Deal with lookups that yield a NULL ptr
				if (attr_str_table_ptr) {
					HPIOS_DEBUG_PRINTF(
						DBG_TEXT("%4s Adap=%d %s ")
						DBG_TEXT("ctl_idx=0x%04x %s %s\n"),
						szFileline, phm->wAdapterIndex,
						hpi_function_string(phm->wFunction),
						wIndex,
						get_treenode_elem(&hpi_control_type_strings, controlType, DBG_CHAR *, idx_out_of_bounds_str),
						get_treenode_elem(attr_str_table_ptr, attrIndex, DBG_CHAR *, idx_out_of_bounds_str)
						);
				} else {
					HPIOS_DEBUG_PRINTF(
						DBG_TEXT("%4s Adap=%d %s ")
						DBG_TEXT("ctl_idx=0x%04x %s invalid_attrib=0x%04x\n"),
						szFileline, phm->wAdapterIndex,
						hpi_function_string(phm->wFunction),
						wIndex,
						get_treenode_elem(&hpi_control_type_strings, controlType, DBG_CHAR *, idx_out_of_bounds_str),
						attrIndex
						);
				}
			} else
				HPIOS_DEBUG_PRINTF(
					DBG_TEXT("%4s Adap=%d %s ")
					DBG_TEXT("obj_idx=0x%04x attrib=0x%04x \n"),
					szFileline, phm->wAdapterIndex,
					hpi_function_string(phm->wFunction),
					wIndex, wAttrib);
		} else {
			HPIOS_DEBUG_PRINTF(
					DBG_TEXT("%4s Adap=%d, Invalid Obj=%d, Func=0x%x\n"),
					   szFileline, phm->wAdapterIndex, phm->wObject,
					   phm->wFunction);
		}
	} else
		HPIOS_DEBUG_PRINTF(HPI_DEBUG_FLAG_ERROR
			DBG_TEXT("NULL message pointer to hpi_debug_message!\n"));
}
#else
void hpi_debug_message(HPI_MESSAGE *phm, DBG_CHAR * szFileline)
{
	if (phm) {
		printk(KERN_DEBUG "HPI_MSG%d,%d,%d,%d,%d\n",
		phm->version,
		phm->wAdapterIndex,
		phm->wObjIndex,
		phm->wFunction,
		phm->u.c.wAttribute);
	}

}
#endif
void hpi_debug_data(uint16_t *pdata, uint32_t len)
{
	uint32_t i;
	int j;
	int k;
	int lines;
	int cols = 8;

	lines = (len + cols - 1) / cols;
	if (lines > 8)
		lines = 8;

	for (i = 0, j = 0; j < lines; j++) {
		HPIOS_DEBUG_PRINTF(HPI_DEBUG_FLAG_VERBOSE DBG_TEXT("%p:"), (pdata + i));

		for (k = 0; k < cols && i < len; i++, k++)
			HPIOS_DEBUG_PRINTF(DBG_TEXT("%s%04x"),
					   k == 0 ? "" : " ", pdata[i]);

		HPIOS_DEBUG_PRINTF(DBG_TEXT("\n"));
	}
}

#ifdef SGT_SERIAL_LOGGING
///////////////////////////////////////////////////////////////////////////////
// SGT
void HpiDebug_SerialLog_Init(void)
{
#define COM1_PORT_ADDRESS 0x3F8
#define MAX_STRING 40

	int ch = 0, i = 0;
	char sz[MAX_STRING];

	HOUT8(COM1_PORT_ADDRESS + 1, 0);	// Turn off interrupts - Port1
	HOUT8(COM1_PORT_ADDRESS + 3, 0x80);	// SET DLAB ON */
	HOUT8(COM1_PORT_ADDRESS + 0, 0x01);	// Set Baud rate - Divisor Latch Low Byte  = 115,200BPS
	HOUT8(COM1_PORT_ADDRESS + 1, 0x00);	// Set Baud rate - Divisor Latch High Byte
	HOUT8(COM1_PORT_ADDRESS + 3, 0x03);	// 8 Bits, No Parity, 1 Stop Bit
	HOUT8(COM1_PORT_ADDRESS + 2, 0xC7);	// FIFO Control Register
	HOUT8(COM1_PORT_ADDRESS + 4, 0x0B);	// Turn on DTR, RTS, and OUT2

	HOUT8(COM1_PORT_ADDRESS, '\r');	// Send Char to Serial Port
	HOUT8(COM1_PORT_ADDRESS, '\n');	// Send Char to Serial Port
	HOUT8(COM1_PORT_ADDRESS, '\n');	// Send Char to Serial Port
	HOUT8(COM1_PORT_ADDRESS, '*');	// Send Char to Serial Port
	HOUT8(COM1_PORT_ADDRESS, '\r');	// Send Char to Serial Port
	HOUT8(COM1_PORT_ADDRESS, '\n');	// Send Char to Serial Port
}

void HpiDebug_SerialLog_SendBuffer(char *pszBuffer)
{
	int i = 0;
	unsigned char bLSR = 0;

	/*
	   for(i=0; i<80; i++)
	   {
	   if(pszBuffer[i]==0)
	   break;
	   do
	   {
	   bLSR = HINP8(COM1_PORT_ADDRESS+5);
	   }while((bLSR & 0x20)!= 0x20);        // wait till bit5 is high

	   HOUT8(COM1_PORT_ADDRESS+0, pszBuffer[i]);
	   }
	   // seems like the terminal s/w needs to see a \r\n to get a full LF/CR
	   if(i>0)
	   if(pszBuffer[i-1] == '\n')
	   HOUT8(COM1_PORT_ADDRESS+0,'\r');
	 */
	do {
		bLSR = HINP8(COM1_PORT_ADDRESS + 5);
	} while ((bLSR & 0x20) != 0x20);	// wait till bit5 is high - 16char FIFO buffer is empty

	for (i = 0; i < 14; i++) {
		if ((pszBuffer[i] == 0) || (pszBuffer[i] == '\n'))
			break;
		HOUT8(COM1_PORT_ADDRESS + 0, pszBuffer[i]);
	}
	// seems like the terminal s/w needs to see a \r\n to get a full LF/CR
	if ((pszBuffer[i] == '\n') || (i == 14)) {
		HOUT8(COM1_PORT_ADDRESS + 0, '\r');
		HOUT8(COM1_PORT_ADDRESS + 0, '\n');
	}
}
#endif
