/******************************************************************************
HPI internal definitions

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 )

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

#ifndef _HPI_INTERNAL_H_
#define _HPI_INTERNAL_H_

#include "hpi.h"

/** maximum number of memory regions mapped to an adapter */
#define HPI_MAX_ADAPTER_MEM_SPACES (3)
#define HPI_MSI_MESSAGE_COUNT (2)

/* Each OS needs its own hpios.h */
#include <hpios.h>

#if defined(HPI_OS_WDM) || defined(HPI_OS_WIN32_USER)

/* HPI IOCTL definitions, shared by windows user and kernel modes */
#define HPI_IOCTL_WINNT_OLD  CTL_CODE(50000,0xA00,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define HPI_IOCTL_WINNT      CTL_CODE(50000,0xA01,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define HPI_IOCTL_WIN95      0x101

/* HPI start device failure log filename shared by windows user and kernel modes */
#define HPI_ASISDFL_FILENAME	L"asi_failure.txt"

#ifndef HPI_API
#define HPI_API(a) a
#endif

#ifndef HPI_CALLBACK
#define HPI_CALLBACK
#endif

#endif	// not LINUX

#ifndef HPI_OS_LINUX_KERNEL

#ifndef __user
#define __user
#endif
#ifndef __iomem
#define __iomem
#endif

#endif /* HPI_OS_LINUX_KERNEL */

#ifndef HPI_BUILD_SANITISE
#ifndef HPIOS_MEMWRITEBLK32
#define HPIOS_MEMWRITEBLK32(to, from, nwords) do {\
		int i;\
		uint32_t *src = from;\
		for (i = 0; i < nwords; i++)\
			HPIOS_MEMWRITE32(to, *src++);\
} while (0)
#endif

#ifndef HPIOS_MEMREADBLK32
#define HPIOS_MEMREADBLK32(from, to, nwords)  do {\
	int i;\
	uint32_t *dst = to;\
	for (i = 0; i < nwords; i++)\
		*dst++ = HPIOS_MEMREAD32(from);\
} while (0)
#endif
#endif

#ifndef HPI_LOCKING

#define DSPLOCK_TYPE int
#define OSTYPE_VALIDFLAG int

#define HpiOs_Mutex_Init(obj)
#define HpiOs_Mutex_Lock(obj)
#define HpiOs_Mutex_Unlock(obj)

#endif

#ifndef HPI_OS_LINUX_KERNEL
/* memory allocation */
#ifndef HpiOs_MemAlloc
void *HpiOs_MemAlloc(uint32_t dwSize);
#endif
#ifndef HpiOs_MemAllocZero
void *HpiOs_MemAllocZero(uint32_t dwSize);
#endif
#ifndef HpiOs_MemFree
void HpiOs_MemFree(void *ptr);
#endif
#endif

/* physical memory allocation */
#ifndef HPI_NO_OS_LOCKEDMEM_OPS
#ifndef HPI_BUILD_SANITISE
void HpiOs_LockedMem_Init(
	void
);
void HpiOs_LockedMem_FreeAll(
	void
);
#endif

/** Allocate and map an area of locked memory for bus master DMA operations.

On success, *pLockedMemeHandle is a valid handle, and vaddr returned
On error *pLockedMemHandle marked invalid, NULL returend

If this function succeeds, then HpiOs_LockedMem_GetVirtAddr() and
HpiOs_LockedMem_GetPyhsAddr() will always succed on the returned handle.
*/
void * HpiOs_LockedMem_Alloc(
	HpiOs_LockedMem_Handle * pLockedMemHandle,  /**< memory handle */
	uint32_t dwSize, /**< Size in bytes to allocate */
	struct hpi_os_adapter *pa,
	/**< OS specific data required for memory allocation */
	uint32_t *pPhysicalAddress
#ifdef HPI_LOG_LOCKED_MEM
	, const char *pFileName, int nLineNumber
#endif
);

/** Free mapping and memory represented by LockedMemHandle

Frees any resources, then invalidates the handle.
If handle is invalid, do nothing.
*/
void HpiOs_LockedMem_Free(
	HpiOs_LockedMem_Handle *LockedMemHandle
#ifdef HPI_LOG_LOCKED_MEM
	, const char *pFileName, int nLineNumber
#endif
);

/** Get the physical PCI address of memory represented by LockedMemHandle.

If handle is invalid return zero
*/
uint32_t HpiOs_LockedMem_GetPhysAddr(
	HpiOs_LockedMem_Handle *LockedMemHandle
);

/** Get the CPU address of of memory represented by LockedMemHandle.

If handle is invalid return NULL
*/
void * HpiOs_LockedMem_GetVirtAddr(
	HpiOs_LockedMem_Handle *LockedMemHandle
);

/** Check that handle is valid
i.e it represents a valid memory area
*/
hpi_err_t HpiOs_LockedMem_Valid(
	HpiOs_LockedMem_Handle *LockedMemHandle
);

#ifndef HPI_BUILD_SANITISE
/** Check that address is valid
i.e it represents a memory address in this locked mem allocation
*/
uint16_t HpiOs_LockedMem_ValidAddr(
	HpiOs_LockedMem_Handle *LockedMemHandle,
	void  *pvVirtualAddr
);

// Could this move to hpios_wdm.h?
#ifdef HPI_LOG_LOCKED_MEM
#define HpiOs_LockedMem_Alloc(a,b,c)	\
	HpiOs_LockedMem_Alloc(a,b,c,__FILE__,__LINE__)
#define HpiOs_LockedMem_Free(a)		\
	HpiOs_LockedMem_Free(a,__FILE__,__LINE__)
#define HPI_DEBUG_LEVEL_LOCKED_MEM_DEBUG_LEVEL HPI_DEBUG_LEVEL_WARNING
#define HPI_DEBUG_FLAG_LOCKED_MEM_DEBUG_LEVEL
#else
#define HPI_DEBUG_LEVEL_LOCKED_MEM_DEBUG_LEVEL HPI_DEBUG_LEVEL_DEBUG
#define HPI_DEBUG_FLAG_LOCKED_MEM_DEBUG_LEVEL
#endif
#endif

#define HpiOs_BoundaryFreeBufferAllocSize(size) \
		( size * 2 )

#define HpiOs_NextBoundary(addr,interval) (( addr + interval ) & ~(interval-1))

/* Use division to determine if the buffer crosses an interval boundary,
 * avoiding overflow when addr is near the top of 32-bit address space.
 */
#define HpiOs_BoundaryFreeBufferOffset(size, interval, addr) \
		( ( (uint32_t)(addr) / (interval) == \
		    ((uint32_t)(addr) + (uint32_t)(size) - 1) / (interval) ) ? \
			( 0 ) : ( (interval) - ((uint32_t)(addr) & ((interval) - 1)) ) )
			
#endif

/* timing/delay */
void HpiOs_DelayMicroSeconds(
	uint32_t dwNumMicroSec
);

#ifndef HPI_NO_OS_FILE_OPS
#ifndef HpiOs_fopen_rb
/* functions not implemented as macros in OS.h files */
hpi_err_t HpiOs_fopen_rb(
	const char *filename,
	HpiOs_FILE * pFile
);
int HpiOs_fseek(
	HpiOs_FILE stream,
	long offset,
	int origin
);
int HpiOs_fread(
	void *buffer,
	size_t size,
	size_t count,
	HpiOs_FILE stream
);
int HpiOs_fclose(
	HpiOs_FILE stream
);
#endif

const char *HpiOs_GetDspCodePath(
	uint32_t nAdapter
);
void HpiOs_SetDspCodePath(
	const char *pPath
);
#endif

struct hpi_message;
struct hpi_response;
struct hpi_adapter_obj;


#ifndef HPI_OS_LINUX_KERNEL
/** A 6 byte ethernet mac address */
typedef uint8_t hpi_ethernet_mac_adr_t[6];
#define HPI_ETHERNET_MAC_ADR hpi_ethernet_mac_adr_t
#endif

#ifndef HPI_BUILD_SANITISE
/* A few convenience macros */
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(A) (sizeof(A)/sizeof((A)[0]))
#endif

#ifndef max
#define max(a,b)            (((a) > (b)) ? (a) : (b))
#endif

#ifndef min
#define min(a,b)            (((a) < (b)) ? (a) : (b))
#endif

#ifndef __stringify
#define __stringify_1(x) #x
#define __stringify(x) __stringify_1(x)
#endif

#define HPI_UNUSED(param) (void)param

/** init a buffer that can be sized, from a constant 'C'.
Note that all the sizeof and conditionals are evaluated at
compile time, so this reduces to a memcpy with constant count.
*/
#define HPI_STRCPY_C(dst, src) do { \
	if (sizeof(src) <= sizeof(dst))\
		memcpy(dst, src, sizeof(src));\
	else {\
		memcpy(dst, src, sizeof(dst)-1);\
		dst[sizeof(dst)-1] = 0;\
	} \
} while (0)

/** strncpy with null terminator 'Z' insertion */
#define HPI_STRNCPY_Z(dst, src, dst_len) do { \
	strncpy(dst, src, dst_len);\
	dst[dst_len-1] = 0;\
} while (0)

/* strncpy when dst is char array that gives correct sizeof (not char*) 'SD'
and with null terminator insertion 'Z' */
#define HPI_STRNCPY_SDZ(dst, src) HPI_STRNCPY_Z(dst, src, sizeof(dst))

#endif

/* If the assert fails, compiler complains
   something like size of array `msg' is negative.
   Unlike linux BUILD_BUG_ON, this works outside function scope.
*/
#define compile_time_assert(cond, msg) \
    typedef char ASSERT_##msg[(cond) ? 1 : -1]

#ifdef __cplusplus
/* *INDENT-OFF* */
extern "C" {
/* *INDENT-ON* */
#endif

/*/////////////////////////////////////////////////////////////////////////// */
/* Private HPI Entity related definitions                                     */

#define STR_SIZE_FIELD_MAX 65535U
#define STR_TYPE_FIELD_MAX 255U
#define STR_ROLE_FIELD_MAX 255U

#if defined(_MSC_VER)
#pragma warning( push )
#pragma warning( disable : 4200 )
#endif

struct hpi_entity {
	uint16_t size;
	uint8_t type;
	uint8_t role;
};

#if defined(_MSC_VER)
#pragma warning( pop )
#endif

compile_time_assert((sizeof(struct hpi_entity) == 4), sizeof_hpi_entity);

static inline size_t hpi_entity_size(struct hpi_entity *entity_ptr) {
	return entity_ptr->size;
}

static inline size_t hpi_entity_header_size(void)
{
	return sizeof(struct hpi_entity);
}

static inline size_t hpi_entity_value_size(struct hpi_entity *entity_ptr)
{
	return hpi_entity_size(entity_ptr) - hpi_entity_header_size();
}

static inline void *hpi_entity_value_ptr(struct hpi_entity *entity_ptr)
{
	return entity_ptr + 1;
}

static inline struct hpi_entity *hpi_entity_ptr_to_next(struct hpi_entity *entity_ptr)
{
	return (struct hpi_entity *)(((uint8_t*)entity_ptr) + hpi_entity_size(entity_ptr));
}

static inline int hpi_entity_read_int_value(int *ptr)
{
	return *ptr;
}

/******************************************* bus types */
enum HPI_BUSES {
	HPI_BUS_ISAPNP = 1,
	HPI_BUS_PCI = 2,
	HPI_BUS_USB = 3,
	HPI_BUS_NET = 4,
	HPI_BUS_SW = 5
};

enum HPI_SUBSYS_OPTIONS {
	/* 0, 256 are invalid, 1..255 reserved for global options */
	HPI_SUBSYS_OPT_NET_ENABLE = 257,
	HPI_SUBSYS_OPT_NET_BROADCAST = 258,
	HPI_SUBSYS_OPT_NET_UNICAST = 259,
	HPI_SUBSYS_OPT_NET_ADDR = 260,
	HPI_SUBSYS_OPT_NET_MASK = 261,
	HPI_SUBSYS_OPT_NET_ADAPTER_ADDRESS_ADD = 262
};

/** Volume flags
*/
enum HPI_VOLUME_FLAGS {
	/** Set if the volume control is muted */
	HPI_VOLUME_FLAG_MUTED = (1 << 0),
	/** Set if the volume control has a mute function */
	HPI_VOLUME_FLAG_HAS_MUTE = (1 << 1),
	/** Set if volume control can do autofading */
	HPI_VOLUME_FLAG_HAS_AUTOFADE = (1 << 2)
	/* Note Flags >= (1<<8) are for DSP internal use only */
};

/******************************************* CONTROL ATTRIBUTES ****/
/* (in order of control type ID */

/* This allows for 255 control types, 256 unique attributes each */
#define HPI_CTL_ATTR(ctl, ai) ((HPI_CONTROL_##ctl << 8) + ai)

/* Get the sub-index of the attribute for a control type */
#define HPI_CTL_ATTR_INDEX(i) (i & 0xff)

/* Extract the control from the control attribute */
#define HPI_CTL_ATTR_CONTROL(i) (i >> 8)


/** Enable event generation for a control.
0=disable, 1=enable
\note generic to all controls that can generate events
*/

/** Unique identifiers for every control attribute
*/
enum HPI_CONTROL_ATTRIBUTES {
	HPI_GENERIC_ENABLE		= HPI_CTL_ATTR(GENERIC, 1),
	HPI_GENERIC_EVENT_ENABLE	= HPI_CTL_ATTR(GENERIC, 2),

	HPI_VOLUME_GAIN			= HPI_CTL_ATTR(VOLUME, 1),
	HPI_VOLUME_AUTOFADE		= HPI_CTL_ATTR(VOLUME, 2),
	HPI_VOLUME_MUTE			= HPI_CTL_ATTR(VOLUME, 3),
	HPI_VOLUME_GAIN_AND_FLAGS	= HPI_CTL_ATTR(VOLUME, 4),
	HPI_VOLUME_NUM_CHANNELS		= HPI_CTL_ATTR(VOLUME, 6),
	HPI_VOLUME_RANGE		= HPI_CTL_ATTR(VOLUME, 10),

	HPI_METER_RMS			= HPI_CTL_ATTR(METER, 1),
	HPI_METER_PEAK			= HPI_CTL_ATTR(METER, 2),
	HPI_METER_RMS_BALLISTICS	= HPI_CTL_ATTR(METER, 3),
	HPI_METER_PEAK_BALLISTICS	= HPI_CTL_ATTR(METER, 4),
	HPI_METER_NUM_CHANNELS		= HPI_CTL_ATTR(METER, 5),

	HPI_MULTIPLEXER_SOURCE		= HPI_CTL_ATTR(MULTIPLEXER, 1),
	HPI_MULTIPLEXER_QUERYSOURCE	= HPI_CTL_ATTR(MULTIPLEXER, 2),

	HPI_AESEBUTX_FORMAT		= HPI_CTL_ATTR(AESEBUTX, 1),
	HPI_AESEBUTX_SAMPLERATE		= HPI_CTL_ATTR(AESEBUTX, 3),
	HPI_AESEBUTX_CHANNELSTATUS	= HPI_CTL_ATTR(AESEBUTX, 4),
	HPI_AESEBUTX_USERDATA		= HPI_CTL_ATTR(AESEBUTX, 5),

	HPI_AESEBURX_FORMAT		= HPI_CTL_ATTR(AESEBURX, 1),
	HPI_AESEBURX_ERRORSTATUS	= HPI_CTL_ATTR(AESEBURX, 2),
	HPI_AESEBURX_SAMPLERATE		= HPI_CTL_ATTR(AESEBURX, 3),
	HPI_AESEBURX_CHANNELSTATUS	= HPI_CTL_ATTR(AESEBURX, 4),
	HPI_AESEBURX_USERDATA		= HPI_CTL_ATTR(AESEBURX, 5),

	HPI_LEVEL_GAIN			= HPI_CTL_ATTR(LEVEL, 1),
	HPI_LEVEL_RANGE			= HPI_CTL_ATTR(LEVEL, 10),

	HPI_TUNER_BAND			= HPI_CTL_ATTR(TUNER, 1),
	HPI_TUNER_FREQ			= HPI_CTL_ATTR(TUNER, 2),
	HPI_TUNER_LEVEL_AVG		= HPI_CTL_ATTR(TUNER, 3),
	HPI_TUNER_LEVEL_RAW		= HPI_CTL_ATTR(TUNER, 4),
	HPI_TUNER_SNR			= HPI_CTL_ATTR(TUNER, 5),
	HPI_TUNER_GAIN			= HPI_CTL_ATTR(TUNER, 6),
	HPI_TUNER_STATUS		= HPI_CTL_ATTR(TUNER, 7),
	HPI_TUNER_MODE			= HPI_CTL_ATTR(TUNER, 8),
	HPI_TUNER_RDS			= HPI_CTL_ATTR(TUNER, 9),
	HPI_TUNER_DEEMPHASIS		= HPI_CTL_ATTR(TUNER, 10),
	HPI_TUNER_PROGRAM		= HPI_CTL_ATTR(TUNER, 11),
	HPI_TUNER_HDRADIO_SIGNAL_QUALITY = HPI_CTL_ATTR(TUNER, 12),
	HPI_TUNER_HDRADIO_SDK_VERSION	= HPI_CTL_ATTR(TUNER, 13),
	HPI_TUNER_HDRADIO_DSP_VERSION	= HPI_CTL_ATTR(TUNER, 14),
	HPI_TUNER_HDRADIO_BLEND		= HPI_CTL_ATTR(TUNER, 15),
	HPI_TUNER_DABRADIO_AS		= HPI_CTL_ATTR(TUNER, 16),
	HPI_TUNER_DABRADIO_ASC		= HPI_CTL_ATTR(TUNER, 17),
	HPI_TUNER_DABRADIO_MULTIPLEX_NAME	= HPI_CTL_ATTR(TUNER, 18),
	HPI_TUNER_DABRADIO_MULTIPLEX_ID		= HPI_CTL_ATTR(TUNER, 19),
	HPI_TUNER_DABRADIO_SERVICE_ID		= HPI_CTL_ATTR(TUNER, 20),
	HPI_TUNER_DABRADIO_AUDIO_INFO		= HPI_CTL_ATTR(TUNER, 21),

	HPI_TUNER_DABRADIO_SERVICE_INFO		= HPI_CTL_ATTR(TUNER, 22),
	HPI_TUNER_DABRADIO_COMPONENT_INFO	= HPI_CTL_ATTR(TUNER, 23),
	HPI_TUNER_DABRADIO_SERVICE		= HPI_CTL_ATTR(TUNER, 24),
	HPI_TUNER_DABRADIO_DIGITAL_DATA		= HPI_CTL_ATTR(TUNER, 25),
	HPI_TUNER_BACKGROUND_PROC		= HPI_CTL_ATTR(TUNER, 26),
	HPI_TUNER_DIRECT_MSG			= HPI_CTL_ATTR(TUNER, 27),



	HPI_VOX_THRESHOLD		= HPI_CTL_ATTR(VOX, 1),

	HPI_CHANNEL_MODE_MODE		= HPI_CTL_ATTR(CHANNEL_MODE, 1),

	HPI_BITSTREAM_DATA_POLARITY	= HPI_CTL_ATTR(BITSTREAM, 1),
	HPI_BITSTREAM_CLOCK_EDGE	= HPI_CTL_ATTR(BITSTREAM, 2),
	HPI_BITSTREAM_CLOCK_SOURCE	= HPI_CTL_ATTR(BITSTREAM, 3),
	HPI_BITSTREAM_ACTIVITY		= HPI_CTL_ATTR(BITSTREAM, 4),

	HPI_SAMPLECLOCK_SOURCE		= HPI_CTL_ATTR(SAMPLECLOCK, 1),
	HPI_SAMPLECLOCK_SAMPLERATE	= HPI_CTL_ATTR(SAMPLECLOCK, 2),
	HPI_SAMPLECLOCK_SOURCE_INDEX	= HPI_CTL_ATTR(SAMPLECLOCK, 3),
	HPI_SAMPLECLOCK_LOCAL_SAMPLERATE = HPI_CTL_ATTR(SAMPLECLOCK, 4),
	HPI_SAMPLECLOCK_AUTO		= HPI_CTL_ATTR(SAMPLECLOCK, 5),
	HPI_SAMPLECLOCK_LOCAL_LOCK	= HPI_CTL_ATTR(SAMPLECLOCK, 6),
	HPI_SAMPLECLOCK_LOCAL_SAMPLERATE_EX = HPI_CTL_ATTR(SAMPLECLOCK, 7),

	HPI_MICROPHONE_PHANTOM_POWER	= HPI_CTL_ATTR(MICROPHONE, 1),

	HPI_EQUALIZER_NUM_FILTERS	= HPI_CTL_ATTR(EQUALIZER, 1),
	HPI_EQUALIZER_FILTER		= HPI_CTL_ATTR(EQUALIZER, 2),
	HPI_EQUALIZER_COEFFICIENTS	= HPI_CTL_ATTR(EQUALIZER, 3),

	HPI_COMPANDER_PARAMS		= HPI_CTL_ATTR(COMPANDER, 1),
	HPI_COMPANDER_MAKEUPGAIN	= HPI_CTL_ATTR(COMPANDER, 2),
	HPI_COMPANDER_THRESHOLD		= HPI_CTL_ATTR(COMPANDER, 3),
	HPI_COMPANDER_RATIO		= HPI_CTL_ATTR(COMPANDER, 4),
	HPI_COMPANDER_ATTACK		= HPI_CTL_ATTR(COMPANDER, 5),
	HPI_COMPANDER_DECAY		= HPI_CTL_ATTR(COMPANDER, 6),

	HPI_COBRANET_SET		= HPI_CTL_ATTR(COBRANET, 1),
	HPI_COBRANET_GET		= HPI_CTL_ATTR(COBRANET, 2),
#ifdef HPI_OS_DELETE
	/*HPI_COBRANET_SET_DATA		= HPI_CTL_ATTR(COBRANET, 3),*/
	/*HPI_COBRANET_GET_DATA		= HPI_CTL_ATTR(COBRANET, 4),*/
#endif
	HPI_COBRANET_GET_STATUS		= HPI_CTL_ATTR(COBRANET, 5),
	HPI_COBRANET_SEND_PACKET	= HPI_CTL_ATTR(COBRANET, 6),
	HPI_COBRANET_GET_PACKET		= HPI_CTL_ATTR(COBRANET, 7),

	HPI_TONEDETECTOR_THRESHOLD	= HPI_CTL_ATTR(TONEDETECTOR, 1),
	HPI_TONEDETECTOR_STATE		= HPI_CTL_ATTR(TONEDETECTOR, 2),
	HPI_TONEDETECTOR_FREQUENCY	= HPI_CTL_ATTR(TONEDETECTOR, 3),

	HPI_SILENCEDETECTOR_THRESHOLD	= HPI_CTL_ATTR(SILENCEDETECTOR, 1),
	HPI_SILENCEDETECTOR_STATE	= HPI_CTL_ATTR(SILENCEDETECTOR, 2),
	HPI_SILENCEDETECTOR_DELAY	= HPI_CTL_ATTR(SILENCEDETECTOR, 3),

	HPI_PAD_CHANNEL_NAME		= HPI_CTL_ATTR(PAD, 1),
	HPI_PAD_ARTIST			= HPI_CTL_ATTR(PAD, 2),
	HPI_PAD_TITLE			= HPI_CTL_ATTR(PAD, 3),
	HPI_PAD_COMMENT			= HPI_CTL_ATTR(PAD, 4),
	HPI_PAD_PROGRAM_TYPE		= HPI_CTL_ATTR(PAD, 5),
	HPI_PAD_PROGRAM_ID		= HPI_CTL_ATTR(PAD, 6),
	HPI_PAD_TA_SUPPORT		= HPI_CTL_ATTR(PAD, 7),
	HPI_PAD_TA_ACTIVE		= HPI_CTL_ATTR(PAD, 8),

	HPI_UNIVERSAL_ENTITY = HPI_CTL_ATTR(UNIVERSAL, 1)
};

#define HPI_POLARITY_POSITIVE		0
#define HPI_POLARITY_NEGATIVE		1

/*------------------------------------------------------------
 Cobranet Chip Bridge - copied from HMI.H
------------------------------------------------------------*/
#define  HPI_COBRANET_HMI_cobraBridge		0x20000
#define  HPI_COBRANET_HMI_cobraBridgeTxPktBuf \
	(HPI_COBRANET_HMI_cobraBridge + 0x1000)
#define  HPI_COBRANET_HMI_cobraBridgeRxPktBuf \
	(HPI_COBRANET_HMI_cobraBridge + 0x2000)
#define  HPI_COBRANET_HMI_cobraIfTable1		0x110000
#define  HPI_COBRANET_HMI_cobraIfPhyAddress \
	(HPI_COBRANET_HMI_cobraIfTable1 + 0xd)
#define  HPI_COBRANET_HMI_cobraProtocolIP	0x72000
#define  HPI_COBRANET_HMI_cobraIpMonCurrentIP \
	(HPI_COBRANET_HMI_cobraProtocolIP + 0x0)
#define  HPI_COBRANET_HMI_cobraIpMonStaticIP \
	(HPI_COBRANET_HMI_cobraProtocolIP + 0x2)
#define  HPI_COBRANET_HMI_cobraSys		0x100000
#define  HPI_COBRANET_HMI_cobraSysDesc \
		(HPI_COBRANET_HMI_cobraSys + 0x0)
#define  HPI_COBRANET_HMI_cobraSysObjectID \
	(HPI_COBRANET_HMI_cobraSys + 0x100)
#define  HPI_COBRANET_HMI_cobraSysContact \
	(HPI_COBRANET_HMI_cobraSys + 0x200)
#define  HPI_COBRANET_HMI_cobraSysName \
		(HPI_COBRANET_HMI_cobraSys + 0x300)
#define  HPI_COBRANET_HMI_cobraSysLocation \
	(HPI_COBRANET_HMI_cobraSys + 0x400)

/*------------------------------------------------------------
 Cobranet Chip Status bits
------------------------------------------------------------*/
#define HPI_COBRANET_HMI_STATUS_RXPACKET 2
#define HPI_COBRANET_HMI_STATUS_TXPACKET 3

/*------------------------------------------------------------
 Ethernet header size
------------------------------------------------------------*/
#define HPI_ETHERNET_HEADER_SIZE (16)

/* These defines are used to fill in protocol information for an Ethernet packet
    sent using HMI on CS18102 */
/** ID supplied by Cirrus for ASI packets. */
#define HPI_ETHERNET_PACKET_ID			0x85
/** Simple packet - no special routing required */
#define HPI_ETHERNET_PACKET_V1			0x01
/** This packet must make its way to the host across the HPI interface */
#define HPI_ETHERNET_PACKET_HOSTED_VIA_HMI	0x20
/** This packet must make its way to the host across the HPI interface */
#define HPI_ETHERNET_PACKET_HOSTED_VIA_HMI_V1	0x21
/** This packet must make its way to the host across the HPI interface */
#define HPI_ETHERNET_PACKET_HOSTED_VIA_HPI	0x40
/** This packet must make its way to the host across the HPI interface */
#define HPI_ETHERNET_PACKET_HOSTED_VIA_HPI_V1	0x41

#define HPI_ETHERNET_UDP_PORT 44600 /**< HPI UDP service */

/** Default network timeout in milli-seconds. */
#define HPI_ETHERNET_TIMEOUT_MS 500

/** Locked memory buffer alloc/free phases */
enum HPI_BUFFER_CMDS {
	/** use one message to allocate or free physical memory */
	HPI_BUFFER_CMD_EXTERNAL = 0,
	/** alloc physical memory */
	HPI_BUFFER_CMD_INTERNAL_ALLOC = 1,
	/** send physical memory address to adapter */
	HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER = 2,
	/** notify adapter to stop using physical buffer */
	HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER = 3,
	/** free physical buffer */
	HPI_BUFFER_CMD_INTERNAL_FREE = 4
};

/*****************************************************************************/
/*****************************************************************************/
/********		HPI LOW LEVEL MESSAGES			*******/
/*****************************************************************************/
/*****************************************************************************/
/** Pnp ids */
/** "ASI"  - actual is "ASX" - need to change */
#define HPI_ID_ISAPNP_AUDIOSCIENCE	0x0669
/** PCI vendor ID that AudioScience uses */
#define HPI_PCI_VENDOR_ID_AUDIOSCIENCE	0x175C
/** PCI vendor ID that TI uses */
#define HPI_PCI_VENDOR_ID_TI		0x104C

#define HPI_PCI_DEV_ID_PCI2040		0xAC60
/** TI's C6205 PCI interface has this ID */
#define HPI_PCI_DEV_ID_DSP6205		0xA106
/** TI's TMS320DM8147 PCIe interface has this ID */
#define HPI_PCI_DEV_ID_DM8147		0xB801

#define HPI_USB_VENDOR_ID_AUDIOSCIENCE	0x1257
#define HPI_USB_W2K_TAG			0x57495341	/* "ASIW"       */
#define HPI_USB_LINUX_TAG		0x4C495341	/* "ASIL"       */

#ifndef HPI_OS_LINUX_KERNEL
/** Flash keys */
enum FLASH_KEYS {
	/** Firmware download key for asi24xx */
	HPI_FLASH_KEY_FIRMWARE_ASI = 0x0A51,
	/** Firmware download key for asi23xx*/
	HPI_FLASH_KEY_FIRMWARE_BOOT = 0x544F4F42,
	HPI_FLASH_KEY_FIRMWARE_FACT = 0x54434146,
	HPI_FLASH_KEY_FIRMWARE_USER = 0x52455355,
	/** FileStore lua source code key */
	HPI_FLASH_KEY_LUA_SOURCE = 0x5A5A,
	/** FileStore lua bytecode key */
	HPI_FLASH_KEY_LUA_BYTECODE = 0xA5A5
};
#endif
/** Invalid Adapter index
Used in HPI messages that are not addressed to a specific adapter
Used in DLL to indicate device not present
*/
#define HPI_ADAPTER_INDEX_INVALID 0xFFFF

/** First 2 hex digits define the adapter family */
#define HPI_ADAPTER_FAMILY_MASK		0xff00
#define HPI_MODULE_FAMILY_MASK		0xfff0

#define HPI_ADAPTER_FAMILY_ASI(f)   (f & HPI_ADAPTER_FAMILY_MASK)
#define HPI_MODULE_FAMILY_ASI(f)   (f & HPI_MODULE_FAMILY_MASK)
#define HPI_ADAPTER_ASI(f)   (f)

enum HPI_MESSAGE_TYPES {
	HPI_TYPE_REQUEST		= 1,
	HPI_TYPE_RESPONSE		= 2,
	HPI_TYPE_DATA			= 3,
	HPI_TYPE_SSX2BYPASS_MESSAGE	= 4,
	HPI_TYPE_COMMAND		= 5,
	HPI_TYPE_NOTIFICATION		= 6
};

enum HPI_OBJECT_TYPES {
	HPI_OBJ_SUBSYSTEM	= 1,
	HPI_OBJ_ADAPTER		= 2,
	HPI_OBJ_OSTREAM		= 3,
	HPI_OBJ_ISTREAM		= 4,
	HPI_OBJ_MIXER		= 5,
	HPI_OBJ_NODE		= 6,
	HPI_OBJ_CONTROL		= 7,
	HPI_OBJ_NVMEMORY	= 8,
	HPI_OBJ_GPIO		= 9,
	HPI_OBJ_WATCHDOG	= 10,
	HPI_OBJ_CLOCK		= 11,
	HPI_OBJ_PROFILE		= 12,
	/* HPI_ OBJ_ CONTROLEX	= 13, */
	HPI_OBJ_ASYNCEVENT	= 14

	#define HPI_OBJ_MAXINDEX 14
};

#define HPI_OBJ_FUNCTION_SPACING 0x100
#define HPI_FUNC_ID(obj, i) (HPI_OBJ_##obj * HPI_OBJ_FUNCTION_SPACING + i)

#define HPI_EXTRACT_INDEX(fn) (fn & 0xff)

enum HPI_FUNCTION_IDS {
	HPI_SUBSYS_OPEN			= HPI_FUNC_ID(SUBSYSTEM, 1),
	HPI_SUBSYS_GET_VERSION		= HPI_FUNC_ID(SUBSYSTEM, 2),
	HPI_SUBSYS_GET_INFO		= HPI_FUNC_ID(SUBSYSTEM, 3),
#ifdef HPI_OS_DELETE
	HPI_SUBSYS_FIND_ADAPTERS	= HPI_FUNC_ID(SUBSYSTEM, 4),
#endif
	HPI_SUBSYS_CREATE_ADAPTER	= HPI_FUNC_ID(SUBSYSTEM, 5),
	HPI_SUBSYS_CLOSE		= HPI_FUNC_ID(SUBSYSTEM, 6),
#ifdef HPI_OS_DELETE
	HPI_SUBSYS_DELETE_ADAPTER	= HPI_FUNC_ID(SUBSYSTEM, 7),
#endif
	HPI_SUBSYS_DRIVER_LOAD		= HPI_FUNC_ID(SUBSYSTEM, 8),
	HPI_SUBSYS_DRIVER_UNLOAD	= HPI_FUNC_ID(SUBSYSTEM, 9),
#ifdef HPI_OS_DELETE
	HPI_SUBSYS_READ_PORT_8	= HPI_FUNC_ID(SUBSYSTEM, 10),
	HPI_SUBSYS_WRITE_PORT_8	= HPI_FUNC_ID(SUBSYSTEM, 11),
#endif
	HPI_SUBSYS_GET_NUM_ADAPTERS	= HPI_FUNC_ID(SUBSYSTEM, 12),
	HPI_SUBSYS_GET_ADAPTER		= HPI_FUNC_ID(SUBSYSTEM, 13),
	HPI_SUBSYS_SET_NETWORK_INTERFACE = HPI_FUNC_ID(SUBSYSTEM, 14),
	HPI_SUBSYS_OPTION_INFO = HPI_FUNC_ID(SUBSYSTEM, 15),
	HPI_SUBSYS_OPTION_GET = HPI_FUNC_ID(SUBSYSTEM, 16),
	HPI_SUBSYS_OPTION_SET = HPI_FUNC_ID(SUBSYSTEM, 17),
	HPI_SUBSYS_WAKE_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 18),
	#define HPI_SUBSYS_FUNCTION_COUNT 18

	HPI_ADAPTER_OPEN		= HPI_FUNC_ID(ADAPTER, 1),
	HPI_ADAPTER_CLOSE		= HPI_FUNC_ID(ADAPTER, 2),
	HPI_ADAPTER_GET_INFO		= HPI_FUNC_ID(ADAPTER, 3),
	HPI_ADAPTER_GET_ASSERT		= HPI_FUNC_ID(ADAPTER, 4),
	HPI_ADAPTER_TEST_ASSERT		= HPI_FUNC_ID(ADAPTER, 5),
	HPI_ADAPTER_SET_MODE		= HPI_FUNC_ID(ADAPTER, 6),
	HPI_ADAPTER_GET_MODE		= HPI_FUNC_ID(ADAPTER, 7),
	HPI_ADAPTER_ENABLE_CAPABILITY	= HPI_FUNC_ID(ADAPTER, 8),
	HPI_ADAPTER_SELFTEST		= HPI_FUNC_ID(ADAPTER, 9),
	HPI_ADAPTER_FIND_OBJECT		= HPI_FUNC_ID(ADAPTER, 10),
	HPI_ADAPTER_QUERY_FLASH		= HPI_FUNC_ID(ADAPTER, 11),
	HPI_ADAPTER_START_FLASH		= HPI_FUNC_ID(ADAPTER, 12),
	HPI_ADAPTER_PROGRAM_FLASH	= HPI_FUNC_ID(ADAPTER, 13),
	HPI_ADAPTER_SET_PROPERTY	= HPI_FUNC_ID(ADAPTER, 14),
	HPI_ADAPTER_GET_PROPERTY	= HPI_FUNC_ID(ADAPTER, 15),
	HPI_ADAPTER_ENUM_PROPERTY	= HPI_FUNC_ID(ADAPTER, 16),
	HPI_ADAPTER_MODULE_INFO		= HPI_FUNC_ID(ADAPTER, 17),
	HPI_ADAPTER_DEBUG_READ		= HPI_FUNC_ID(ADAPTER, 18),
	HPI_ADAPTER_IRQ_QUERY_AND_CLEAR = HPI_FUNC_ID(ADAPTER, 19),
	HPI_ADAPTER_IRQ_CALLBACK	= HPI_FUNC_ID(ADAPTER, 20),
	HPI_ADAPTER_DELETE		= HPI_FUNC_ID(ADAPTER, 21),
	HPI_ADAPTER_READ_FLASH		= HPI_FUNC_ID(ADAPTER, 22),
	HPI_ADAPTER_END_FLASH		= HPI_FUNC_ID(ADAPTER, 23),
	HPI_ADAPTER_FILESTORE_DELETE_ALL = HPI_FUNC_ID(ADAPTER, 24),
	#define HPI_ADAPTER_FUNCTION_COUNT 24

	HPI_OSTREAM_OPEN		= HPI_FUNC_ID(OSTREAM, 1),
	HPI_OSTREAM_CLOSE		= HPI_FUNC_ID(OSTREAM, 2),
	HPI_OSTREAM_WRITE		= HPI_FUNC_ID(OSTREAM, 3),
	HPI_OSTREAM_START		= HPI_FUNC_ID(OSTREAM, 4),
	HPI_OSTREAM_STOP		= HPI_FUNC_ID(OSTREAM, 5),
	HPI_OSTREAM_RESET		= HPI_FUNC_ID(OSTREAM, 6),
	HPI_OSTREAM_GET_INFO		= HPI_FUNC_ID(OSTREAM, 7),
	HPI_OSTREAM_QUERY_FORMAT	= HPI_FUNC_ID(OSTREAM, 8),
	HPI_OSTREAM_DATA		= HPI_FUNC_ID(OSTREAM, 9),
	HPI_OSTREAM_SET_VELOCITY	= HPI_FUNC_ID(OSTREAM, 10),
	HPI_OSTREAM_SET_PUNCHINOUT	= HPI_FUNC_ID(OSTREAM, 11),
	HPI_OSTREAM_SINEGEN		= HPI_FUNC_ID(OSTREAM, 12),
	HPI_OSTREAM_ANC_RESET		= HPI_FUNC_ID(OSTREAM, 13),
	HPI_OSTREAM_ANC_GET_INFO	= HPI_FUNC_ID(OSTREAM, 14),
	HPI_OSTREAM_ANC_READ		= HPI_FUNC_ID(OSTREAM, 15),
	HPI_OSTREAM_SET_TIMESCALE	= HPI_FUNC_ID(OSTREAM, 16),
	HPI_OSTREAM_SET_FORMAT		= HPI_FUNC_ID(OSTREAM, 17),
	HPI_OSTREAM_HOSTBUFFER_ALLOC	= HPI_FUNC_ID(OSTREAM, 18),
	HPI_OSTREAM_HOSTBUFFER_FREE	= HPI_FUNC_ID(OSTREAM, 19),
	HPI_OSTREAM_GROUP_ADD		= HPI_FUNC_ID(OSTREAM, 20),
	HPI_OSTREAM_GROUP_GETMAP	= HPI_FUNC_ID(OSTREAM, 21),
	HPI_OSTREAM_GROUP_RESET		= HPI_FUNC_ID(OSTREAM, 22),
	HPI_OSTREAM_HOSTBUFFER_GET_INFO	= HPI_FUNC_ID(OSTREAM, 23),
	HPI_OSTREAM_WAIT_START		= HPI_FUNC_ID(OSTREAM, 24),
	HPI_OSTREAM_WAIT		= HPI_FUNC_ID(OSTREAM, 25),
	HPI_OSTREAM_GET_TIMESTAMP	= HPI_FUNC_ID(OSTREAM, 26),
	#define HPI_OSTREAM_FUNCTION_COUNT 26

	HPI_ISTREAM_OPEN		= HPI_FUNC_ID(ISTREAM, 1),
	HPI_ISTREAM_CLOSE		= HPI_FUNC_ID(ISTREAM, 2),
	HPI_ISTREAM_SET_FORMAT		= HPI_FUNC_ID(ISTREAM, 3),
	HPI_ISTREAM_READ		= HPI_FUNC_ID(ISTREAM, 4),
	HPI_ISTREAM_START		= HPI_FUNC_ID(ISTREAM, 5),
	HPI_ISTREAM_STOP		= HPI_FUNC_ID(ISTREAM, 6),
	HPI_ISTREAM_RESET		= HPI_FUNC_ID(ISTREAM, 7),
	HPI_ISTREAM_GET_INFO		= HPI_FUNC_ID(ISTREAM, 8),
	HPI_ISTREAM_QUERY_FORMAT	= HPI_FUNC_ID(ISTREAM, 9),
	HPI_ISTREAM_ANC_RESET		= HPI_FUNC_ID(ISTREAM, 10),
	HPI_ISTREAM_ANC_GET_INFO	= HPI_FUNC_ID(ISTREAM, 11),
	HPI_ISTREAM_ANC_WRITE		= HPI_FUNC_ID(ISTREAM, 12),
	HPI_ISTREAM_HOSTBUFFER_ALLOC	= HPI_FUNC_ID(ISTREAM, 13),
	HPI_ISTREAM_HOSTBUFFER_FREE	= HPI_FUNC_ID(ISTREAM, 14),
	HPI_ISTREAM_GROUP_ADD		= HPI_FUNC_ID(ISTREAM, 15),
	HPI_ISTREAM_GROUP_GETMAP	= HPI_FUNC_ID(ISTREAM, 16),
	HPI_ISTREAM_GROUP_RESET		= HPI_FUNC_ID(ISTREAM, 17),
	HPI_ISTREAM_HOSTBUFFER_GET_INFO	= HPI_FUNC_ID(ISTREAM, 18),
	HPI_ISTREAM_WAIT_START		= HPI_FUNC_ID(ISTREAM, 19),
	HPI_ISTREAM_WAIT		= HPI_FUNC_ID(ISTREAM, 20),
	HPI_ISTREAM_GET_TIMESTAMP	= HPI_FUNC_ID(ISTREAM, 21),
	#define HPI_ISTREAM_FUNCTION_COUNT 21

/* NOTE:
   GET_NODE_INFO, SET_CONNECTION, GET_CONNECTIONS are not currently used */
	HPI_MIXER_OPEN			= HPI_FUNC_ID(MIXER, 1),
	HPI_MIXER_CLOSE			= HPI_FUNC_ID(MIXER, 2),
	HPI_MIXER_GET_INFO		= HPI_FUNC_ID(MIXER, 3),
	HPI_MIXER_GET_NODE_INFO		= HPI_FUNC_ID(MIXER, 4),
	HPI_MIXER_GET_CONTROL		= HPI_FUNC_ID(MIXER, 5),
	HPI_MIXER_SET_CONNECTION	= HPI_FUNC_ID(MIXER, 6),
	HPI_MIXER_GET_CONNECTIONS	= HPI_FUNC_ID(MIXER, 7),
	HPI_MIXER_GET_CONTROL_BY_INDEX	= HPI_FUNC_ID(MIXER, 8),
	HPI_MIXER_GET_CONTROL_ARRAY_BY_INDEX = HPI_FUNC_ID(MIXER, 9),
	HPI_MIXER_GET_CONTROL_MULTIPLE_VALUES = HPI_FUNC_ID(MIXER, 10),
	HPI_MIXER_STORE			= HPI_FUNC_ID(MIXER, 11),
	HPI_MIXER_GET_CACHE_INFO	= HPI_FUNC_ID(MIXER, 12),
	HPI_MIXER_GET_BLOCK_HANDLE	= HPI_FUNC_ID(MIXER, 13),
	HPI_MIXER_GET_PARAMETER_HANDLE	= HPI_FUNC_ID(MIXER, 14),
	HPI_MIXER_STORE_STATUS		= HPI_FUNC_ID(MIXER, 15),
#define HPI_MIXER_FUNCTION_COUNT 15

	HPI_CONTROL_GET_INFO		= HPI_FUNC_ID(CONTROL, 1),
	HPI_CONTROL_GET_STATE		= HPI_FUNC_ID(CONTROL, 2),
	HPI_CONTROL_SET_STATE		= HPI_FUNC_ID(CONTROL, 3),
	#define HPI_CONTROL_FUNCTION_COUNT 3

	HPI_NVMEMORY_OPEN		= HPI_FUNC_ID(NVMEMORY, 1),
	HPI_NVMEMORY_READ_BYTE		= HPI_FUNC_ID(NVMEMORY, 2),
	HPI_NVMEMORY_WRITE_BYTE		= HPI_FUNC_ID(NVMEMORY, 3),
	#define HPI_NVMEMORY_FUNCTION_COUNT 3

	HPI_GPIO_OPEN			= HPI_FUNC_ID(GPIO, 1),
	HPI_GPIO_READ_BIT		= HPI_FUNC_ID(GPIO, 2),
	HPI_GPIO_WRITE_BIT		= HPI_FUNC_ID(GPIO, 3),
	HPI_GPIO_READ_ALL		= HPI_FUNC_ID(GPIO, 4),
	HPI_GPIO_WRITE_STATUS		= HPI_FUNC_ID(GPIO, 5),
	#define HPI_GPIO_FUNCTION_COUNT 5

	HPI_ASYNCEVENT_OPEN		= HPI_FUNC_ID(ASYNCEVENT, 1),
	HPI_ASYNCEVENT_CLOSE		= HPI_FUNC_ID(ASYNCEVENT, 2),
	HPI_ASYNCEVENT_WAIT		= HPI_FUNC_ID(ASYNCEVENT, 3),
	HPI_ASYNCEVENT_GETCOUNT		= HPI_FUNC_ID(ASYNCEVENT, 4),
	HPI_ASYNCEVENT_GET		= HPI_FUNC_ID(ASYNCEVENT, 5),
	HPI_ASYNCEVENT_SENDEVENTS	= HPI_FUNC_ID(ASYNCEVENT, 6),
	#define HPI_ASYNCEVENT_FUNCTION_COUNT 6

	HPI_WATCHDOG_OPEN		= HPI_FUNC_ID(WATCHDOG, 1),
	HPI_WATCHDOG_SET_TIME		= HPI_FUNC_ID(WATCHDOG, 2),
	HPI_WATCHDOG_PING		= HPI_FUNC_ID(WATCHDOG, 3),

	HPI_CLOCK_OPEN			= HPI_FUNC_ID(CLOCK, 1),
	HPI_CLOCK_SET_TIME		= HPI_FUNC_ID(CLOCK, 2),
	HPI_CLOCK_GET_TIME		= HPI_FUNC_ID(CLOCK, 3),

	HPI_PROFILE_OPEN_ALL		= HPI_FUNC_ID(PROFILE, 1),
	HPI_PROFILE_START_ALL		= HPI_FUNC_ID(PROFILE, 2),
	HPI_PROFILE_STOP_ALL		= HPI_FUNC_ID(PROFILE, 3),
	HPI_PROFILE_GET			= HPI_FUNC_ID(PROFILE, 4),
	HPI_PROFILE_GET_IDLECOUNT	= HPI_FUNC_ID(PROFILE, 5),
	HPI_PROFILE_GET_NAME		= HPI_FUNC_ID(PROFILE, 6),
	HPI_PROFILE_GET_UTILIZATION	= HPI_FUNC_ID(PROFILE, 7)
	#define HPI_PROFILE_FUNCTION_COUNT 7
};

/* ////////////////////////////////////////////////////////////////////// */
/* STRUCTURES */
#ifndef DISABLE_PRAGMA_PACK1
#pragma pack(push, 1)
#endif

/** Adapter specification resource */
struct hpi_adapter_specification {
	uint16_t wType;
	uint16_t wHwRevision;
	uint8_t modules[4];
};

struct hpi_resource {
	union {
		const char *net_if;
		struct hpi_adapter_specification adapter_spec;
	} r;
	uint16_t wBusType;	/* HPI_BUS_PNPISA, _PCI, _USB etc */
	uint16_t wPadding;
};

/** Format info used inside struct hpi_message
    Not the same as public API struct hpi_format */
struct hpi_msg_format {
	uint32_t dwSampleRate; /**< 11025, 32000, 44100 etc. */
	uint32_t dwBitRate; /**< for MPEG */
	uint32_t dwAttributes; /**< Stereo/JointStereo/Mono */
	uint16_t wChannels; /**< 1,2..., (or ancillary mode or idle bit */
	uint16_t wFormat; /**< HPI_FORMAT_PCM16, _MPEG etc. see \ref HPI_FORMATS. */
};

/**  Buffer+format structure.
	 Must be kept 7 * 32 bits to match public HPI_DATA struct */
struct hpi_msg_data {
	struct hpi_msg_format format;
	uint8_t *pbData;
#ifndef HPI_BUILD_64BIT
	uint32_t dwPadding;
#endif
	uint32_t dwDataSize;
};

/** HPI_DATA structure used up to 3.04 driver */
struct hpi_data_legacy32 {
	struct hpi_format format;
	uint32_t pbData;
	uint32_t dwDataSize;
};

#ifdef HPI_BUILD_64BIT
/* Compatibility version of HPI_DATA */
struct hpi_data_compat32 {
	struct hpi_msg_format format;
	uint32_t pbData;
	uint32_t dwPadding;
	uint32_t dwDataSize;
};
#endif

struct hpi_buffer {
#ifdef HPI_OS_LINUX_KERNEL
	/** placeholder for backward compatibility */
	uint32_t reserved[4];
#else
	/** placeholder for backward compatibility (see dwBufferSize) */
	uint32_t reserved[3];
	uint32_t dwPciAddress64_hi32;  /**< Most significant 32 bits of buffer physical address*/
#endif
	uint32_t dwCommand; /**< HPI_BUFFER_CMD_xxx*/
	uint32_t dwPciAddress; /**< PCI physical address of buffer for DSP DMA */
	uint32_t dwBufferSize; /**< must line up with dwDataSize of HPI_DATA*/
};

/*/////////////////////////////////////////////////////////////////////////// */
/* This is used for background buffer bus mastering stream buffers.           */
struct hpi_hostbuffer_status {
	uint32_t dwSamplesProcessed;
	uint32_t dwAuxiliaryDataAvailable;
	uint32_t dwStreamState;
	// DSP index in to the host bus master buffer.
	uint32_t dwDspIndex;
	// Host index in to the host bus master buffer.
	uint32_t dwHostIndex;
	uint32_t dwSizeInBytes;
};

struct hpi_hostbuffer_status_ex {
	uint32_t dwSamplesProcessed;
	uint32_t dwAuxiliaryDataAvailable;
	uint32_t dwStreamState;
	// DSP index in to the host bus master buffer.
	uint32_t dwDspIndex;
	// Host index in to the host bus master buffer.
	uint32_t dwHostIndex;
	uint32_t dwSizeInBytes;
	int64_t qwPtpTimestamp;
	uint32_t dwNsPerSample;
};

struct hpi_streamid {
	uint16_t wObjectType;
		    /**< Type of object, HPI_OBJ_OSTREAM or HPI_OBJ_ISTREAM. */
	uint16_t wStreamIndex; /**< OStream or IStream index. */
};

struct hpi_punchinout {
	uint32_t dwPunchInSample;
	uint32_t dwPunchOutSample;
};

struct hpi_subsys_msg {
	struct hpi_resource resource;
};

struct hpi_subsys_res {
	uint32_t dwVersion;
	uint32_t dwData; /* extended version */
	uint16_t wNumAdapters;
	uint16_t wAdapterIndex;
	uint16_t wAdapterType;
	uint16_t pad16;
};

union hpi_adapterx_msg {
	struct {
		uint32_t dwDspAddress;
		uint32_t dwCountBytes;
	} debug_read;
	struct {
		uint32_t adapter_mode;
		uint16_t query_or_set;
	} mode;
	struct {
		uint16_t index;
	} module_info;
	struct {
		uint16_t wIndex;
		uint16_t wWhat;
		uint16_t wPropertyIndex;
	} property_enum;
	struct {
		uint16_t wProperty;
		uint16_t wParameter1;
		uint16_t wParameter2;
	} property_set;
	struct {
		uint32_t pad32;
		uint16_t key1;
		uint16_t key2;
	} restart;
	struct {
		uint32_t pad32;
		uint16_t value;
	} test_assert;
	struct {
		uint32_t message ;
	} irq;
	uint32_t pad[3];
};

struct hpi_adapter_res {
	uint32_t dwSerialNumber;
	uint16_t wAdapterType;
	uint16_t wAdapterIndex;
	uint16_t wNumIStreams;
	uint16_t wNumOStreams;
	uint16_t wNumMixers;
	uint16_t wVersion;
	uint8_t szAdapterAssert[HPI_STRING_LEN];
};

union hpi_adapterx_res {
	struct  hpi_adapter_res info;
	struct {
		uint32_t p1;
		uint16_t count;
		uint16_t dsp_index;
		uint32_t p2;
		uint32_t dsp_msg_addr;
		char szMessage[HPI_STRING_LEN];
	} assert;
	struct {
		uint32_t adapter_mode;
	} mode;
	struct {
		uint16_t wParameter1;
		uint16_t wParameter2;
	} property_get;
	struct {
		uint32_t yes;
	} irq_query;
};

struct hpi_stream_msg {
	union {
		struct hpi_msg_data data;
		struct hpi_data_legacy32 data32;
		uint16_t wVelocity;
		struct hpi_punchinout pio;
		uint32_t dwTimeScale;
		struct hpi_buffer buffer;
		struct hpi_streamid stream;
		uint32_t dwThresholdBytes;
	} u;
};

struct hpi_stream_res {
	union {
		struct {
			/* size of hardware buffer */
			uint32_t dwBufferSize;
			/* OutStream - data to play,
			   InStream - data recorded */
			uint32_t dwDataAvailable;
			/* OutStream - samples played,
			   InStream - samples recorded */
			uint32_t dwSamplesTransferred;
			/* Adapter - OutStream - data to play,
			   InStream - data recorded */
			uint32_t dwAuxiliaryDataAvailable;
			uint16_t wState;	/* HPI_STATE_PLAYING, _STATE_STOPPED */
			uint16_t wPadding;
		} stream_info;
		struct {
			uint32_t dwBufferSize;
			uint32_t dwDataAvailable;
			uint32_t dwSamplesTransfered;
			uint16_t wState;
			uint16_t wOStreamIndex;
			uint16_t wIStreamIndex;
			uint16_t wPadding;
			uint32_t dwAuxiliaryDataAvailable;
		} legacy_stream_info;
		struct {
			/* bitmap of grouped OutStreams */
			uint32_t dwOutStreamGroupMap;
			/* bitmap of grouped InStreams */
			uint32_t dwInStreamGroupMap;
		} group_info;
		struct {
			/* pointer to the buffer */
			uint8_t *pBuffer;
			/* pointer to the hostbuffer status */
			struct hpi_hostbuffer_status *pStatus;
		} hostbuffer_info;
		/*
		 * TI C6000 compiler cannot pack structs due to
		 * hardware load/store restrictions. Additionally,
		 * the length of the structure is padded with addition
		 * memory so that the length is an exact multiple of
		 * the largest structure member. This means that using
		 * a 64-bit field can add more memory than intended.
		 * Here the 64-bit gPTP timestamp is split in to
		 * 2 32-bit entries to avoid this issue.
		 */
		struct {
			uint32_t dwSample;
			uint32_t dwNsPerSample;
			uint32_t qwPtpTimestampHi;
			uint32_t qwPtpTimestampLo;
		} timestamp_info;
	} u;
};

struct hpi_mixer_msg {
	uint16_t wControlIndex;
	uint16_t wControlType;	/* = HPI_CONTROL_METER _VOLUME etc */
	uint16_t wPadding1;		/* Maintain alignment of subsequent fields */
	uint16_t wNodeType1;	/* = HPI_SOURCENODE_LINEIN etc */
	uint16_t wNodeIndex1;	/* = 0..N */
	uint16_t wNodeType2;
	uint16_t wNodeIndex2;
	uint16_t wPadding2;		/* round to 4 bytes */
};

struct hpi_mixer_res {
	uint16_t wSrcNodeType;	/* = HPI_SOURCENODE_LINEIN etc */
	uint16_t wSrcNodeIndex;	/* = 0..N */
	uint16_t wDstNodeType;
	uint16_t wDstNodeIndex;
	/* Also controlType for MixerGetControlByIndex */
	uint16_t wControlIndex;
	/* may indicate which DSP the control is located on */
	uint16_t wDspIndex;
};

union hpi_mixerx_msg {
	struct {
		uint16_t wStartingIndex;
		uint16_t wFlags;
		uint32_t dwLengthInBytes;	/* length in bytes of pData */
		uint32_t pData;	/* pointer to a data array */
	} gcabi;
	struct {
		uint16_t wCommand;
		uint16_t wIndex;
	} store;		/* for HPI_MIXER_STORE message */
};

union hpi_mixerx_res {
	struct {
		uint32_t dwBytesReturned;	/* size of items returned */
		uint32_t pData;	/* pointer to data array */
		uint16_t wMoreToDo;	/* indicates if there is more to do */
	} gcabi;
	struct {
		uint32_t total_controls; /* count of controls in the mixer */
		uint32_t cache_controls; /* count of controls in the cac */
		uint32_t cache_bytes;	/* size of cache */
	} cache_info;
	struct {
		uint16_t wControlCount;
	} store;		/* for HPI_MIXER_STORE_STATUS message */
};

struct hpi_control_msg {
	uint16_t wAttribute;	/* control attribute or property */
	uint16_t wSavedIndex;
	uint32_t dwParam1;		/* generic parameter 1 */
	uint32_t dwParam2;		/* generic parameter 2 */
	short anLogValue[HPI_MAX_CHANNELS];
};

struct hpi_control_union_msg {
	uint16_t wAttribute;	/* control attribute or property */
	uint16_t wSavedIndex;	/* Only used in ctrl save/restore */
	union {
		struct {
			uint32_t dwParam1;	/* generic parameter 1 */
			uint32_t dwParam2;	/* generic parameter 2 */
			short anLogValue[HPI_MAX_CHANNELS];
		} old;
		union {
			uint32_t dwFrequency;
			uint32_t dwGain;
			uint32_t dwBand;
			uint32_t dwDeemphasis;
			uint32_t dwProgram;
			struct {
				uint32_t dwMode;
				uint32_t dwValue;
			} mode;
			uint32_t dwBlend;
		} tuner;
	} u;
};

struct hpi_control_res {
	/* Could make union. dwParam, anLogValue never used in same response */
	uint32_t dwParam1;
	uint32_t dwParam2;
	short anLogValue[HPI_MAX_CHANNELS];
};

union hpi_control_union_res {
	struct {
		uint32_t dwParam1;
		uint32_t dwParam2;
		short anLogValue[HPI_MAX_CHANNELS];
	} old;
	union {
		uint32_t dwBand;
		uint32_t dwFrequency;
		uint32_t dwGain;
		uint32_t dwDeemphasis;
		struct {
			uint32_t dwData[2];
			uint32_t dwBLER;
		} rds;
		short sLevel;
		struct {
			uint16_t value;
			uint16_t mask;
		} status;
	} tuner;
	struct {
		char szData[8];
		uint32_t dwRemainingChars;
	} chars8;
	char cData12[12];
	union {
		struct {
			uint32_t dwStatus;
			uint32_t dwReadableSize;
			uint32_t dwWriteableSize;
		} status;
	} cobranet;
};

struct hpi_nvmemory_msg {
	uint16_t wAddress;
	uint16_t wData;
};

struct hpi_nvmemory_res {
	uint16_t wSizeInBytes;
	uint16_t wData;
};

struct hpi_gpio_msg {
	uint16_t wBitIndex;
	uint16_t wBitData;
};

struct hpi_gpio_res {
	uint16_t wNumberInputBits;
	uint16_t wNumberOutputBits;
	uint16_t wBitData[4];
};

struct hpi_async_msg {
	uint32_t dwEvents;
	uint16_t wMaximumEvents;
	uint16_t wPadding;
};

struct hpi_async_res {
	union {
		struct {
			uint16_t wCount;
		} count;
		struct {
			uint32_t dwEvents;
			uint16_t wNumberReturned;
			uint16_t wPadding;
		} get;
		struct hpi_async_event event;
	} u;
};

struct hpi_watchdog_msg {
	uint32_t dwTimeMs;
};

struct hpi_watchdog_res {
	uint32_t dwTimeMs;
};

struct hpi_clock_msg {
	uint16_t wHours;
	uint16_t wMinutes;
	uint16_t wSeconds;
	uint16_t wMilliSeconds;
};

struct hpi_clock_res {
	uint16_t wSizeInBytes;
	uint16_t wHours;
	uint16_t wMinutes;
	uint16_t wSeconds;
	uint16_t wMilliSeconds;
	uint16_t wPadding;
};

struct hpi_profile_msg {
	uint16_t wBinIndex;
	uint16_t wPadding;
};

struct hpi_profile_res_open {
	uint16_t wMaxProfiles;
};

struct hpi_profile_res_time {
	uint32_t dwTotalTickCount;
	uint32_t dwCallCount;
	uint32_t dwMaxTickCount;
	uint32_t dwTicksPerMillisecond;
	uint16_t wProfileInterval;
};

struct hpi_profile_res_name {
	uint8_t szName[32];
};

struct hpi_profile_res {
	union {
		struct hpi_profile_res_open o;
		struct hpi_profile_res_time t;
		struct hpi_profile_res_name n;
	} u;
};

struct hpi_message_header {
	uint16_t wSize;		/* total size in bytes */
	uint8_t wType;		/* HPI_TYPE_MESSAGE  */
	uint8_t version;		/* message version */
	uint16_t wObject;		/* HPI_OBJ_* */
	uint16_t wFunction;		/* HPI_SUBSYS_xxx, HPI_ADAPTER_xxx */
	uint16_t wAdapterIndex;	/* the adapter index */
	uint16_t wObjIndex;		/* */
};

struct hpi_message {
	/* following fields must match struct hpi_message_header */
	uint16_t wSize;		/* total size in bytes */
	uint8_t wType;		/* HPI_TYPE_MESSAGE  */
	uint8_t version;		/* message version */
	uint16_t wObject;		/* HPI_OBJ_* */
	uint16_t wFunction;		/* HPI_SUBSYS_xxx, HPI_ADAPTER_xxx */
	uint16_t wAdapterIndex;	/* the adapter index */
	uint16_t wObjIndex;		/*  */
	union {
		struct hpi_subsys_msg s;
		union hpi_adapterx_msg ax;
		struct hpi_stream_msg d;
		struct hpi_mixer_msg m;
		union hpi_mixerx_msg mx;	/* extended mixer; */
		struct hpi_control_msg c;	/* mixer control; */
		/* identical to struct hpi_control_msg,
		   but field naming is improved */
		struct hpi_control_union_msg cu;
		struct hpi_nvmemory_msg n;
		struct hpi_gpio_msg l;	/* digital i/o */
		struct hpi_watchdog_msg w;
		struct hpi_clock_msg t;	/* dsp time */
		struct hpi_profile_msg p;
		struct hpi_async_msg as;
		char   fixed_size[32];
	} u;
};

#define HPI_MESSAGE_SIZE_BY_OBJECT { \
	sizeof(struct hpi_message_header) ,   /* Default, no object type 0 */ \
	sizeof(struct hpi_message_header) + sizeof(struct hpi_subsys_msg),\
	sizeof(struct hpi_message_header) + sizeof(union hpi_adapterx_msg),\
	sizeof(struct hpi_message_header) + sizeof(struct hpi_stream_msg),\
	sizeof(struct hpi_message_header) + sizeof(struct hpi_stream_msg),\
	sizeof(struct hpi_message_header) + sizeof(struct hpi_mixer_msg),\
	sizeof(struct hpi_message_header) ,   /* no node message */ \
	sizeof(struct hpi_message_header) + sizeof(struct hpi_control_msg),\
	sizeof(struct hpi_message_header) + sizeof(struct hpi_nvmemory_msg),\
	sizeof(struct hpi_message_header) + sizeof(struct hpi_gpio_msg),\
	sizeof(struct hpi_message_header) + sizeof(struct hpi_watchdog_msg),\
	sizeof(struct hpi_message_header) + sizeof(struct hpi_clock_msg),\
	sizeof(struct hpi_message_header) + sizeof(struct hpi_profile_msg),\
	sizeof(struct hpi_message_header), /* controlx obj removed */ \
	sizeof(struct hpi_message_header) + sizeof(struct hpi_async_msg) \
}

/*
Note that the wSpecificError error field should be inspected and potentially
reported whenever HPI_ERROR_DSP_COMMUNICATION or HPI_ERROR_DSP_BOOTLOAD is
returned in wError.
*/
struct hpi_response_header {
	uint16_t wSize;
	uint8_t wType;		/* HPI_TYPE_RESPONSE  */
	uint8_t version;		/* response version */
	uint16_t wObject;		/* HPI_OBJ_* */
	uint16_t wFunction;		/* HPI_SUBSYS_xxx, HPI_ADAPTER_xxx */
	uint16_t wError;		/* HPI_ERROR_xxx */
	uint16_t wSpecificError;	/* Adapter specific error */
};

struct hpi_response {
	/* following fields must match struct hpi_response_header  */
	uint16_t wSize;
	uint8_t wType;		/* HPI_TYPE_RESPONSE  */
	uint8_t version;		/* response version */
	uint16_t wObject;		/* HPI_OBJ_* */
	uint16_t wFunction;		/* HPI_SUBSYS_xxx, HPI_ADAPTER_xxx */
	uint16_t wError;		/* HPI_ERROR_xxx */
	uint16_t wSpecificError;	/* Adapter specific error */
	union {
		struct hpi_subsys_res s;
		union hpi_adapterx_res ax;
		struct hpi_stream_res d;
		struct hpi_mixer_res m;
		union hpi_mixerx_res mx;	/* extended mixer; */
		struct hpi_control_res c;	/* mixer control; */
		/* identical to hpi_control_res, but field naming is improved */
		union hpi_control_union_res cu;
		struct hpi_nvmemory_res n;
		struct hpi_gpio_res l;	/* digital i/o */
		struct hpi_watchdog_res w;
		struct hpi_clock_res t;	/* dsp time */
		struct hpi_profile_res p;
		struct hpi_async_res as;
		uint8_t bytes[52];
	} u;
};

#define HPI_RESPONSE_SIZE_BY_OBJECT { \
	sizeof(struct hpi_response_header) ,/* Default, no object type 0 */ \
	sizeof(struct hpi_response_header) + sizeof(struct hpi_subsys_res),\
	sizeof(struct hpi_response_header) + sizeof(union  hpi_adapterx_res),\
	sizeof(struct hpi_response_header) + sizeof(struct hpi_stream_res),\
	sizeof(struct hpi_response_header) + sizeof(struct hpi_stream_res),\
	sizeof(struct hpi_response_header) + sizeof(struct hpi_mixer_res),\
	sizeof(struct hpi_response_header) , /* no node response */ \
	sizeof(struct hpi_response_header) + sizeof(struct hpi_control_res),\
	sizeof(struct hpi_response_header) + sizeof(struct hpi_nvmemory_res),\
	sizeof(struct hpi_response_header) + sizeof(struct hpi_gpio_res),\
	sizeof(struct hpi_response_header) + sizeof(struct hpi_watchdog_res),\
	sizeof(struct hpi_response_header) + sizeof(struct hpi_clock_res),\
	sizeof(struct hpi_response_header) + sizeof(struct hpi_profile_res),\
	sizeof(struct hpi_response_header), /* controlx obj removed */ \
	sizeof(struct hpi_response_header) + sizeof(struct hpi_async_res) \
}

/*********************** version 1 message/response **************************/
#define HPINET_ETHERNET_DATA_SIZE (1500)
#define HPINET_IP_HDR_SIZE (20)
#define HPINET_IP_DATA_SIZE (HPINET_ETHERNET_DATA_SIZE - HPINET_IP_HDR_SIZE)
#define HPINET_UDP_HDR_SIZE (8)
#define HPINET_UDP_DATA_SIZE (HPINET_IP_DATA_SIZE - HPINET_UDP_HDR_SIZE)
#define HPINET_ASI_HDR_SIZE (2)
#define HPINET_ASI_DATA_SIZE (HPINET_UDP_DATA_SIZE - HPINET_ASI_HDR_SIZE)

#define HPI_MAX_PAYLOAD_SIZE (HPINET_ASI_DATA_SIZE - 2)


/* New style message/response, but still V0 compatible */
struct hpi_msg_adapter_get_info {
	struct hpi_message_header h;
};

struct hpi_res_adapter_get_info {
	struct hpi_response_header h; //v0
	struct hpi_adapter_res p;
};

#ifndef HPI_OS_LINUX_KERNEL
/* padding is so these are same size as v0 hpi_response */
/* used for start and query */
struct hpi_msg_adapter_flash{
	struct hpi_message_header h;
	uint32_t dwOffset;
	uint32_t dwLength;
	uint32_t dwKey;
	uint8_t pad_to_version0_size[
		sizeof(struct hpi_message) - /* V0 res */
		sizeof(struct hpi_message_header) -
		3 * sizeof(uint32_t)];
};

struct hpi_res_adapter_flash {
	struct hpi_response_header h;
	uint32_t dwChecksum;
	uint32_t dwLength;
	uint32_t dwVersion;
	uint32_t dwFamily;
	uint32_t dwMaxLength;
	uint8_t pad_to_version0_size[
		sizeof(struct hpi_response) - /* V0 res */
		sizeof(struct hpi_response_header) -
		5 * sizeof(uint32_t)];
};

struct  hpi_msg_adapter_program_flash_payload {
	uint32_t dwChecksum;
	uint16_t wSequence;
	uint16_t wLength;
	uint16_t wOffset; /**< offset from start of msg to data */
	uint16_t wUnused;
	/* ensure sizeof(header + payload) == sizeof(hpi_message_V0)
	  because old firmware expects data after message of this size */
	uint8_t pad_to_version0_size[
		sizeof(struct hpi_message) - /* V0 message */
		sizeof(struct hpi_message_header) -
		sizeof(uint32_t) -
		4 * sizeof(uint16_t) ];
};

struct  hpi_msg_adapter_program_flash{
	struct hpi_message_header h;
	struct  hpi_msg_adapter_program_flash_payload p;
	uint32_t data[256];
};

struct hpi_res_adapter_program_flash {
	struct hpi_response_header h;
	uint16_t wSequence;
	uint8_t pad_to_version0_size[
		sizeof(struct hpi_response) - /* V0 res */
		sizeof(struct hpi_response_header) -
		sizeof(uint16_t)];
};

struct hpi_msg_adapter_read_flash{
	struct hpi_message_header h;
	uint32_t dwKey;
	uint16_t wSequence;
	uint16_t wLength;
	uint8_t pad_to_version0_size[
		sizeof(struct hpi_message) - /* V0 res */
		sizeof(struct hpi_message_header) -
		sizeof(uint32_t) -
		2 * sizeof(uint16_t)];
};

struct hpi_res_adapter_read_flash {
	struct hpi_response_header h;
	uint32_t dwChecksum;
	uint16_t wSequence;
	uint16_t wLength;
	uint32_t data[256];
};

struct hpi_msg_adapter_debug_read {
	struct hpi_message_header h;
	uint32_t dwDspAddress;
	uint32_t dwCountBytes;
};
#endif
struct hpi_res_adapter_debug_read {
	struct hpi_response_header h;
	uint8_t bytes[1024];
};

struct hpi_msg_cobranet_hmi {
	   uint16_t wAttribute;
	   uint16_t padding;
	   uint32_t dwHmiAddress;
	   uint32_t dwByteCount;
};

struct hpi_msg_cobranet_hmiwrite {
	struct hpi_message_header h;
	struct hpi_msg_cobranet_hmi p;
	uint8_t  bytes[256];
};

struct hpi_msg_cobranet_hmiread {
	struct hpi_message_header h;
	struct hpi_msg_cobranet_hmi p;
};

struct hpi_res_cobranet_hmiread {
	struct hpi_response_header h;
	uint32_t dwByteCount;
	uint8_t  bytes[256];
};

struct hpi_msg_tuner_msg {
	struct hpi_message_header h;
	union {
		struct hpi_control_union_msg cu;
	} u;
	uint16_t tx_byte_count;
	uint16_t rx_byte_count;
	uint8_t msg_bytes[256];
};

struct hpi_res_tuner_msg {
	struct hpi_response_header h;
	uint16_t byte_count;
	uint8_t res_bytes[256];
};

struct hpi_msg_body_control_data {
	uint16_t attribute; /* control attribute */
	uint16_t index2;  /* secondary index, e.g. component ID */
	uint16_t offset;  /* byte offset into data if size > 300 */
	uint16_t byte_count;  /* max to read */
	/* Index for multi item controls e.g. DAB service list
	 * or service id for DAB things addressed by service:component */
	uint32_t index;
};

struct hpi_msg_control_data {
	struct hpi_message_header h;
	struct hpi_msg_body_control_data p;
};

struct hpi_res_body_control_data {
	uint16_t bytes_remaining;  /* after this read or write */
	uint16_t byte_count;  /* in this read */
	uint8_t bytes[1020];
};

struct hpi_res_control_data {
	struct hpi_response_header h;
	struct hpi_res_body_control_data p;
};

// STRV HPI Packet
struct hpi_msg_strv {
	struct hpi_message_header h;
	struct hpi_entity strv;
};
struct hpi_msg_block_handle {
	struct hpi_message_header h;
	struct hpi_mixer_msg m;
	char name[128];
};
struct hpi_msg_parameter_handle {
	struct hpi_message_header h;
	uint32_t block_control_index;
	char name[128];
};

struct hpi_res_strv {
	struct hpi_response_header h;
	struct hpi_entity strv;
};
#define MIN_STRV_PACKET_SIZE sizeof(struct hpi_res_strv)

struct hpi_msg_payload_v0 {
	struct hpi_message_header h;
	union {
		struct hpi_subsys_msg s;
		union hpi_adapterx_msg ax;
		struct hpi_stream_msg d;
		struct hpi_mixer_msg m;
		union hpi_mixerx_msg mx;
		struct hpi_control_msg c;
		struct hpi_control_union_msg cu;
		struct hpi_nvmemory_msg n;
		struct hpi_gpio_msg l;
		struct hpi_watchdog_msg w;
		struct hpi_clock_msg t;
		struct hpi_profile_msg p;
		struct hpi_async_msg as;
	} u;
};

struct hpi_res_payload_v0 {
	struct hpi_response_header h;
	union {
		struct hpi_subsys_res s;
		union hpi_adapterx_res ax;
		struct hpi_stream_res d;
		struct hpi_mixer_res m;
		union hpi_mixerx_res mx;
		struct hpi_control_res c;
		union hpi_control_union_res cu;
		struct hpi_nvmemory_res n;
		struct hpi_gpio_res l;
		struct hpi_watchdog_res w;
		struct hpi_clock_res t;
		struct hpi_profile_res p;
		struct hpi_async_res as;
	} u;
};

union hpi_message_buffer_v1 {
	struct hpi_message m0; /* version 0 */
	struct hpi_message_header h;
	uint8_t buf[HPI_MAX_PAYLOAD_SIZE];
};

union hpi_response_buffer_v1 {
	struct hpi_response r0; /* version 0 */
	struct hpi_response_header h;
	uint8_t buf[HPI_MAX_PAYLOAD_SIZE];
};

compile_time_assert((sizeof(union hpi_message_buffer_v1) <= HPI_MAX_PAYLOAD_SIZE),
	message_buffer_ok);
compile_time_assert((sizeof(union hpi_response_buffer_v1) <= HPI_MAX_PAYLOAD_SIZE),
	response_buffer_ok);

/*////////////////////////////////////////////////////////////////////////// */
/* declarations for compact control calls  */
struct hpi_control_defn {
	uint8_t wType;
	uint8_t wChannels;
	uint8_t wSrcNodeType;
	uint8_t wSrcNodeIndex;
	uint8_t wDestNodeType;
	uint8_t wDestNodeIndex;
};

compile_time_assert((HPI_DESTNODE_LAST_INDEX <= 255), node_type_fits_in_uint8_ok);

/*////////////////////////////////////////////////////////////////////////// */
/* declarations for control caching (internal to HPI<->DSP interaction)      */

/** indicates a cached uint16_t value is invalid. */
#define HPI_CACHE_INVALID_UINT16 0xFFFF
/** indicates a cached short value is invalid. */
#define HPI_CACHE_INVALID_SHORT -32768

/** A compact representation of (part of) a controls state.
Used for efficient transfer of the control state
between DSP and host or across a network
*/
struct hpi_control_cache_info {
	/** one of HPI_CONTROL_* */
	uint8_t ControlType;
	/** The total size of cached information in 32-bit words. */
	uint8_t nSizeIn32bitWords;
	/** The original index of the control on the DSP */
	uint16_t ControlIndex;
};

struct hpi_control_cache_vol {
	struct hpi_control_cache_info i;
	short anLog[2];
	unsigned short flags;
	char padding[2];
};

struct hpi_control_cache_meter {
	struct hpi_control_cache_info i;
	short anLogPeak[2];
	short anLogRMS[2];
};

struct hpi_control_cache_channelmode {
	struct hpi_control_cache_info i;
	uint16_t wMode;
	char temp_padding[6];
};

struct hpi_control_cache_mux {
	struct hpi_control_cache_info i;
	uint16_t wSourceNodeType;
	uint16_t wSourceNodeIndex;
	char temp_padding[4];
};

struct hpi_control_cache_level {
	struct hpi_control_cache_info i;
	short anLog[2];
	char temp_padding[4];
};

struct hpi_control_cache_tuner {
	struct hpi_control_cache_info i;
	uint32_t dwFreqInkHz;
	uint16_t wBand;
	short sLevelAvg;
};

struct hpi_control_cache_aes3rx {
	struct hpi_control_cache_info i;
	uint32_t dwErrorStatus;
	uint32_t dwFormat;
};

struct hpi_control_cache_aes3tx {
	struct hpi_control_cache_info i;
	uint32_t dwFormat;
	char temp_padding[4];
};

struct hpi_control_cache_tonedetector {
	struct hpi_control_cache_info i;
	uint16_t wState;
	uint16_t wEnable;
	char temp_padding[4];
};

struct hpi_control_cache_silencedetector {
	struct hpi_control_cache_info i;
	uint32_t dwState;
	uint16_t wEnable;
	char temp_padding[2];
};

struct hpi_control_cache_sampleclock {
	struct hpi_control_cache_info i;
	uint16_t wSource;
	uint16_t wSourceIndex;
	uint32_t dwSampleRate;
};

struct hpi_control_cache_microphone {
	struct hpi_control_cache_info i;
	uint16_t phantom_state;
	char temp_padding[6];
};

struct hpi_control_cache_strv {
	struct hpi_control_cache_info i;
	struct hpi_entity strv;
};

struct hpi_control_cache_single {
	union {
		struct hpi_control_cache_info i;
		struct hpi_control_cache_vol vol;
		struct hpi_control_cache_meter meter;
		struct hpi_control_cache_channelmode mode;
		struct hpi_control_cache_mux mux;
		struct hpi_control_cache_level level;
		struct hpi_control_cache_tuner tuner;
		struct hpi_control_cache_aes3rx aes3rx;
		struct hpi_control_cache_aes3tx aes3tx;
		struct hpi_control_cache_tonedetector tone;
		struct hpi_control_cache_silencedetector silence;
		struct hpi_control_cache_sampleclock clk;
		struct hpi_control_cache_microphone microphone;
		struct hpi_control_cache_strv strv;
	} u;
};

struct hpi_control_cache_pad {
	struct hpi_control_cache_info i;
	uint32_t dwFieldValidFlags;
	uint8_t cChannel[40];
	uint8_t cArtist[100];
	uint8_t cTitle[100];
	uint8_t cComment[200];
	uint32_t dwPTY;
	uint32_t dwPI;
	uint32_t dwTrafficSupported;
	uint32_t dwTrafficAnouncement;
};

/* 2^N sized FIFO buffer (internal to HPI<->DSP interaction) */
struct hpi_fifo_buffer {
	uint32_t dwSize;
	uint32_t dwDspIndex;
	uint32_t dwHostIndex;
};

#ifndef DISABLE_PRAGMA_PACK1
#pragma pack(pop)
#endif
#ifndef HPI_BUILD_SANITISE
typedef struct hpi_message HPI_MESSAGE;
typedef struct hpi_response HPI_RESPONSE;
#endif

/* skip host side function declarations for DSP
   compile and documentation extraction */

char HPI_HandleObject(const hpi_handle_t dwHandle);

HPI_API_VOID (void) HPI_HandleToIndexes(
	const hpi_handle_t dwHandle,
	uint16_t *pwAdapterIndex,
	uint16_t *pwObjectIndex
);

HPI_API (hpi_handle_t) HPI_IndexesToHandle(
	const char cObject,
	const uint16_t wAdapterIndex,
	const uint16_t wObjectIndex
);

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

/* main HPI entry point */
HPI_API_VOID (void) HPI_Message(
	struct hpi_message *phm,
	struct hpi_response *phr
);

#ifndef HPI_BUILD_KERNEL_MODE
/* UDP message */
void HPI_MessageUDP(
	struct hpi_message *phm,
	struct hpi_response *phr,
	const unsigned int nTimeout
);

uint16_t HPI_DriverOpen(void);
void HPI_DriverClose(void);
#endif

#ifndef HPI_OS_LINUX_KERNEL
/* used in PnP OS/driver */
HPI_API (hpi_err_t) HPI_SubSysCreateAdapter(
	const hpi_hsubsys_t *phSubSys,
	const struct hpi_resource *pResource,
	uint16_t *pwAdapterIndex
);

HPI_API (hpi_err_t) HPI_OutStreamHostBufferGetInfo(
	const hpi_hsubsys_t *phSubSys,
	hpi_handle_t hOutStream,
	uint8_t ** ppBuffer,
	struct hpi_hostbuffer_status **ppStatus
);

HPI_API (hpi_err_t) HPI_InStreamHostBufferGetInfo(
	const hpi_hsubsys_t *phSubSys,
	hpi_handle_t hInStream,
	uint8_t ** ppBuffer,
	struct hpi_hostbuffer_status **ppStatus
);

/*
The following 3 functions were last declared in header files for
driver 3.10. HPI_ControlQuery() used to be the recommended way
of getting a volume range. Declared here for binary asihpi32.dll
compatibility.
*/
HPI_API (hpi_err_t) HPI_ControlParamSet(
	const hpi_hsubsys_t *phSubSys,
	const hpi_handle_t hControl,
	const uint16_t wAttrib,
	const uint32_t dwParam1,
	const uint32_t dwParam2
);
HPI_API (hpi_err_t) HPI_ControlParamGet(
	const hpi_hsubsys_t *phSubSys,
	const hpi_handle_t hControl,
	const uint16_t wAttrib,
	uint32_t dwParam1,
	uint32_t dwParam2,
	uint32_t *pdwParam1,
	uint32_t *pdwParam2
);
HPI_API (hpi_err_t) HPI_ControlQuery(
	const hpi_hsubsys_t *phSubSys,	///< Pointer to HPI subsystem handle
	const hpi_handle_t hControl,	///< Control to query
	const uint16_t wAttrib,	///< An attribute of the control
	const uint32_t dwIndex,	///< Index for possible attribute values
	const uint32_t dwParam,	///< Supplementary parameter
	/** One of N possible settings for the control attribute,
	   specified by dwIndex=0..N-1, and possibly depending on the value
	   of the supplementary parameter) */
	uint32_t *pdwSetting
);

void HPI_FormatToMsg(
	struct hpi_msg_format *pMF,
	const struct hpi_format *pF
);

void HPI_StreamResponseToLegacy(
	struct hpi_stream_res *pSR
);
#endif

#ifdef __cplusplus
/* *INDENT-OFF* */
}
/* *INDENT-ON* */
#endif
#endif				/* _HPI_INTERNAL_H_ */
