/******************************************************************************
hpi_error_text.c

HPI error text function

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 <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <hpi.h>

/*=========================================================================*/
/** \defgroup errors Error codes, and string conversions
@{
*/
/** Convert one of the #HPI_ERROR_CODES into a string
  * @param wError the error code
  * @param pszErrorText pointer to callers buffer. Must be at least 200 bytes!
  */
void HPI_GetErrorText(
	hpi_err_t wError,
	char *pszErrorText
)
{
	strcpy(pszErrorText, " ");
#ifndef HPI_OS_WDM
	sprintf(pszErrorText, "#%3d - ", wError);
#endif

	switch (wError) {
	case 0:
		strcat(pszErrorText, "No Error");
		break;

/**
   Use COG <http://nedbatchelder.com/code/cog/index.html> to parse hpi.h and build
   the body of the HPI_GetErrorText() function. Do not edit manually,
   instead run 'cog -r [thisfile]' to update it.
*/
/*[[[cog

# The following HPI errors will be ignored when generating the case statements for HPI_GetErrorText()
IGNORED_ERRORS = ['HPI_ERROR_UNSUPPORTED_CONTROL_ATTRIBUTE', 'HPI_ERROR_I2C_MISSING_ACK','HPI_ERROR_BACKEND_BASE']

import cog
import re

def parse_hpi_error_definition(inc_file, line):
	tokens = re.split(r'\s+|[=(),]+', line)
	tokens = [t for t in tokens if t]
	# We expect tokens to be as follows:
	# [HPI_ERROR_*, VALUE]
	if len(tokens) > 1:
		return tokens[1], tokens[0]
	else:
		print 'Malformed line? :', line, tokens
		return None

def parse_hpi_error_info(inc_file):
	hpi_errors = []
	while True:
		line = inc_file.readline()
		if not line:
			break
		# Look for HPI_ERROR_* lines
		if line.strip().startswith('HPI_ERROR_'):
			res = parse_hpi_error_definition(inc_file, line)
			if res == None or res[1] in IGNORED_ERRORS:
				continue
			hpi_errors.append(res)
	return hpi_errors

def write_hpi_error_case_stmt(hpi_error_define):
	cog.out('\tcase %s:\n' % hpi_error_define)
	cog.out('\t\tstrcat(pszErrorText, "%s");\n' % hpi_error_define[len('HPI_ERROR_'):])
	cog.out('\t\tbreak;\n')

def gen_case_stmts_for_hpi_errors():
	inc_file = open('hpi.h','rt')
	hpi_errors = parse_hpi_error_info(inc_file)
	inc_file.close()
	# Output generated code
	# The following is an easy way to merge ENUMs that have the same ID
	hpi_errors_dict = dict(hpi_errors)
	for hpi_error_val, hpi_error_define in hpi_errors_dict.items():
		write_hpi_error_case_stmt(hpi_error_define)

gen_case_stmts_for_hpi_errors()
]]]*/
case HPI_ERROR_DSP_FILE_SHARING_VIOLATION:
	strcat(pszErrorText, "DSP_FILE_SHARING_VIOLATION");
	break;
case HPI_ERROR_DSP_FILE_NULL_HEADER:
	strcat(pszErrorText, "DSP_FILE_NULL_HEADER");
	break;
case HPI_ERROR_DSP_SECTION_NOT_FOUND:
	strcat(pszErrorText, "DSP_SECTION_NOT_FOUND");
	break;
case HPI_ERROR_DSP_FILE_OTHER_ERROR:
	strcat(pszErrorText, "DSP_FILE_OTHER_ERROR");
	break;
case HPI_ERROR_DSP_FILE_NO_HEADER:
	strcat(pszErrorText, "DSP_FILE_NO_HEADER");
	break;
case HPI_ERROR_CUSTOM:
	strcat(pszErrorText, "CUSTOM");
	break;
case HPI_ERROR_DSP_FILE_FORMAT:
	strcat(pszErrorText, "DSP_FILE_FORMAT");
	break;
case HPI_ERROR_DSP_FILE_ACCESS_DENIED:
	strcat(pszErrorText, "DSP_FILE_ACCESS_DENIED");
	break;
case HPI_ERROR_TOO_MANY_CAPABILITY_CHANGE_ATTEMPTS:
	strcat(pszErrorText, "TOO_MANY_CAPABILITY_CHANGE_ATTEMPTS");
	break;
case HPI_ERROR_BAD_ADAPTER_MODE:
	strcat(pszErrorText, "BAD_ADAPTER_MODE");
	break;
case HPI_ERROR_INCOMPATIBLE_SAMPLERATE:
	strcat(pszErrorText, "INCOMPATIBLE_SAMPLERATE");
	break;
case HPI_ERROR_INVALID_OPERATION:
	strcat(pszErrorText, "INVALID_OPERATION");
	break;
case HPI_ERROR_INVALID_STRING:
	strcat(pszErrorText, "INVALID_STRING");
	break;
case HPI_ERROR_WAIT_CANCELLED:
	strcat(pszErrorText, "WAIT_CANCELLED");
	break;
case HPI_ERROR_NO_INTERDSP_GROUPS:
	strcat(pszErrorText, "NO_INTERDSP_GROUPS");
	break;
case HPI_ERROR_NO_INTERADAPTER_GROUPS:
	strcat(pszErrorText, "NO_INTERADAPTER_GROUPS");
	break;
case HPI_ERROR_RESPONSE_MISMATCH:
	strcat(pszErrorText, "RESPONSE_MISMATCH");
	break;
case HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL:
	strcat(pszErrorText, "RESPONSE_BUFFER_TOO_SMALL");
	break;
case HPI_ERROR_MESSAGE_BUFFER_TOO_SMALL:
	strcat(pszErrorText, "MESSAGE_BUFFER_TOO_SMALL");
	break;
case HPI_ERROR_CONTROL_CACHING:
	strcat(pszErrorText, "CONTROL_CACHING");
	break;
case HPI_ERROR_INVALID_HANDLE:
	strcat(pszErrorText, "INVALID_HANDLE");
	break;
case HPI_ERROR_NETWORK_TIMEOUT:
	strcat(pszErrorText, "NETWORK_TIMEOUT");
	break;
case HPI_ERROR_NETWORK_TOO_MANY_CLIENTS:
	strcat(pszErrorText, "NETWORK_TOO_MANY_CLIENTS");
	break;
case HPI_ERROR_UNIMPLEMENTED:
	strcat(pszErrorText, "UNIMPLEMENTED");
	break;
case HPI_ERROR_MUTEX_TIMEOUT:
	strcat(pszErrorText, "MUTEX_TIMEOUT");
	break;
case HPI_ERROR_FLASH_SIZE:
	strcat(pszErrorText, "FLASH_SIZE");
	break;
case HPI_ERROR_FLASH_VERIFY:
	strcat(pszErrorText, "FLASH_VERIFY");
	break;
case HPI_ERROR_FLASH_PROGRAM:
	strcat(pszErrorText, "FLASH_PROGRAM");
	break;
case HPI_ERROR_FLASH_ERASE:
	strcat(pszErrorText, "FLASH_ERASE");
	break;
case HPI_ERROR_FLASH_TYPE:
	strcat(pszErrorText, "FLASH_TYPE");
	break;
case HPI_ERROR_CONTROL_NOT_READY:
	strcat(pszErrorText, "CONTROL_NOT_READY");
	break;
case HPI_ERROR_INVALID_NODE:
	strcat(pszErrorText, "INVALID_NODE");
	break;
case HPI_ERROR_CONTROL_I2C_MISSING_ACK:
	strcat(pszErrorText, "CONTROL_I2C_MISSING_ACK");
	break;
case HPI_ERROR_CONTROL_DISABLED:
	strcat(pszErrorText, "CONTROL_DISABLED");
	break;
case HPI_ERROR_INVALID_CONTROL_ATTRIBUTE:
	strcat(pszErrorText, "INVALID_CONTROL_ATTRIBUTE");
	break;
case HPI_ERROR_BAD_CHECKSUM:
	strcat(pszErrorText, "BAD_CHECKSUM");
	break;
case HPI_ERROR_FLASH_START:
	strcat(pszErrorText, "FLASH_START");
	break;
case HPI_ERROR_INVALID_FORMAT:
	strcat(pszErrorText, "INVALID_FORMAT");
	break;
case HPI_ERROR_INVALID_DATA_POINTER:
	strcat(pszErrorText, "INVALID_DATA_POINTER");
	break;
case HPI_ERROR_NVMEM_FAIL:
	strcat(pszErrorText, "NVMEM_FAIL");
	break;
case HPI_ERROR_INVALID_CONTROL_VALUE:
	strcat(pszErrorText, "INVALID_CONTROL_VALUE");
	break;
case HPI_ERROR_BAD_ADAPTER:
	strcat(pszErrorText, "BAD_ADAPTER");
	break;
case HPI_ERROR_INVALID_PACKET_ORDER:
	strcat(pszErrorText, "INVALID_PACKET_ORDER");
	break;
case HPI_ERROR_DUPLICATE_ADAPTER_NUMBER:
	strcat(pszErrorText, "DUPLICATE_ADAPTER_NUMBER");
	break;
case HPI_ERROR_BAD_ADAPTER_NUMBER:
	strcat(pszErrorText, "BAD_ADAPTER_NUMBER");
	break;
case HPI_ERROR_DSP_BOOTLOAD:
	strcat(pszErrorText, "DSP_BOOTLOAD");
	break;
case HPI_ERROR_DSP_HARDWARE:
	strcat(pszErrorText, "DSP_HARDWARE");
	break;
case HPI_ERROR_DSP_FILE_NOT_FOUND:
	strcat(pszErrorText, "DSP_FILE_NOT_FOUND");
	break;
case HPI_ERROR_PLD_LOAD:
	strcat(pszErrorText, "PLD_LOAD");
	break;
case HPI_ERROR_MEMORY_ALLOC:
	strcat(pszErrorText, "MEMORY_ALLOC");
	break;
case HPI_ERROR_INVALID_SAMPLERATE:
	strcat(pszErrorText, "INVALID_SAMPLERATE");
	break;
case HPI_ERROR_INVALID_CHANNELS:
	strcat(pszErrorText, "INVALID_CHANNELS");
	break;
case HPI_ERROR_INVALID_BITRATE:
	strcat(pszErrorText, "INVALID_BITRATE");
	break;
case HPI_ERROR_INVALID_DATASIZE:
	strcat(pszErrorText, "INVALID_DATASIZE");
	break;
case HPI_ERROR_NVMEM_BUSY:
	strcat(pszErrorText, "NVMEM_BUSY");
	break;
case HPI_ERROR_I2C_BAD_ADR:
	strcat(pszErrorText, "I2C_BAD_ADR");
	break;
case HPI_ERROR_INVALID_RESPONSE:
	strcat(pszErrorText, "INVALID_RESPONSE");
	break;
case HPI_ERROR_PROCESSING_MESSAGE:
	strcat(pszErrorText, "PROCESSING_MESSAGE");
	break;
case HPI_ERROR_FLASH_READ_NO_FILE:
	strcat(pszErrorText, "FLASH_READ_NO_FILE");
	break;
case HPI_ERROR_FLASH_READ:
	strcat(pszErrorText, "FLASH_READ");
	break;
case HPI_ERROR_INVALID_FUNC:
	strcat(pszErrorText, "INVALID_FUNC");
	break;
case HPI_ERROR_INVALID_OBJ_INDEX:
	strcat(pszErrorText, "INVALID_OBJ_INDEX");
	break;
case HPI_ERROR_INVALID_TYPE:
	strcat(pszErrorText, "INVALID_TYPE");
	break;
case HPI_ERROR_INVALID_OBJ:
	strcat(pszErrorText, "INVALID_OBJ");
	break;
case HPI_ERROR_INVALID_RESOURCE:
	strcat(pszErrorText, "INVALID_RESOURCE");
	break;
case HPI_ERROR_BAD_SEQUENCE:
	strcat(pszErrorText, "BAD_SEQUENCE");
	break;
case HPI_ERROR_OBJ_NOT_OPEN:
	strcat(pszErrorText, "OBJ_NOT_OPEN");
	break;
case HPI_ERROR_OBJ_ALREADY_OPEN:
	strcat(pszErrorText, "OBJ_ALREADY_OPEN");
	break;
case HPI_ERROR_DSP_COMMUNICATION:
	strcat(pszErrorText, "DSP_COMMUNICATION");
	break;
case HPI_ERROR_INVALID_CONTROL:
	strcat(pszErrorText, "INVALID_CONTROL");
	break;
case HPI_ERROR_NVMEM_FULL:
	strcat(pszErrorText, "NVMEM_FULL");
	break;
case HPI_ERROR_ENTITY_TYPE_INVALID:
	strcat(pszErrorText, "ENTITY_TYPE_INVALID");
	break;
case HPI_ERROR_ENTITY_ROLE_INVALID:
	strcat(pszErrorText, "ENTITY_ROLE_INVALID");
	break;
case HPI_ERROR_ENTITY_TYPE_MISMATCH:
	strcat(pszErrorText, "ENTITY_TYPE_MISMATCH");
	break;
case HPI_ERROR_ENTITY_ITEM_COUNT:
	strcat(pszErrorText, "ENTITY_ITEM_COUNT");
	break;
case HPI_ERROR_ENTITY_SIZE_MISMATCH:
	strcat(pszErrorText, "ENTITY_SIZE_MISMATCH");
	break;
case HPI_ERROR_RESERVED_1:
	strcat(pszErrorText, "RESERVED_1");
	break;
//[[[end]]]

	default:
		strcat(pszErrorText, "Unknown Error");
	}
}
