2019-05-29 17:12:47 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2010-04-21 20:17:39 +04:00
/******************************************************************************
AudioScience HPI driver
2014-11-20 06:22:52 +03:00
Copyright ( C ) 1997 - 2014 AudioScience Inc . < support @ audioscience . com >
2010-04-21 20:17:39 +04:00
\ file hpicmn . c
Common functions used by hpixxxx . c modules
( C ) Copyright AudioScience Inc . 1998 - 2003
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define SOURCEFILE_NAME "hpicmn.c"
# include "hpi_internal.h"
# include "hpidebug.h"
2011-02-10 07:25:58 +03:00
# include "hpimsginit.h"
2010-04-21 20:17:39 +04:00
# include "hpicmn.h"
struct hpi_adapters_list {
struct hpios_spinlock list_lock ;
struct hpi_adapter_obj adapter [ HPI_MAX_ADAPTERS ] ;
u16 gw_num_adapters ;
} ;
static struct hpi_adapters_list adapters ;
/**
2020-07-02 22:35:45 +03:00
* hpi_validate_response - Given an HPI Message that was sent out and
* a response that was received , validate that the response has the
* correct fields filled in , i . e ObjectType , Function etc
* @ phm : message
* @ phr : response
*/
2010-04-21 20:17:39 +04:00
u16 hpi_validate_response ( struct hpi_message * phm , struct hpi_response * phr )
{
2011-02-10 07:25:58 +03:00
if ( phr - > type ! = HPI_TYPE_RESPONSE ) {
2011-02-10 07:26:02 +03:00
HPI_DEBUG_LOG ( ERROR , " header type %d invalid \n " , phr - > type ) ;
2011-02-10 07:25:58 +03:00
return HPI_ERROR_INVALID_RESPONSE ;
}
if ( phr - > object ! = phm - > object ) {
2011-02-10 07:26:02 +03:00
HPI_DEBUG_LOG ( ERROR , " header object %d invalid \n " ,
phr - > object ) ;
2011-02-10 07:25:58 +03:00
return HPI_ERROR_INVALID_RESPONSE ;
}
2010-04-21 20:17:39 +04:00
2011-02-10 07:25:58 +03:00
if ( phr - > function ! = phm - > function ) {
2011-07-22 07:52:50 +04:00
HPI_DEBUG_LOG ( ERROR , " header function %d invalid \n " ,
2011-02-10 07:26:02 +03:00
phr - > function ) ;
2011-02-10 07:25:58 +03:00
return HPI_ERROR_INVALID_RESPONSE ;
}
2010-04-21 20:17:39 +04:00
2011-02-10 07:25:58 +03:00
return 0 ;
2010-04-21 20:17:39 +04:00
}
u16 hpi_add_adapter ( struct hpi_adapter_obj * pao )
{
u16 retval = 0 ;
2011-12-22 04:38:43 +04:00
/*HPI_ASSERT(pao->type); */
2010-04-21 20:17:39 +04:00
hpios_alistlock_lock ( & adapters ) ;
if ( pao - > index > = HPI_MAX_ADAPTERS ) {
retval = HPI_ERROR_BAD_ADAPTER_NUMBER ;
goto unlock ;
}
2011-12-22 04:38:43 +04:00
if ( adapters . adapter [ pao - > index ] . type ) {
2011-02-10 07:26:12 +03:00
int a ;
for ( a = HPI_MAX_ADAPTERS - 1 ; a > = 0 ; a - - ) {
2011-12-22 04:38:43 +04:00
if ( ! adapters . adapter [ a ] . type ) {
2011-02-10 07:26:12 +03:00
HPI_DEBUG_LOG ( WARNING ,
" ASI%X duplicate index %d moved to %d \n " ,
2011-12-22 04:38:43 +04:00
pao - > type , pao - > index , a ) ;
2011-02-10 07:26:12 +03:00
pao - > index = a ;
break ;
}
}
if ( a < 0 ) {
retval = HPI_ERROR_DUPLICATE_ADAPTER_NUMBER ;
2010-04-21 20:17:39 +04:00
goto unlock ;
}
}
adapters . adapter [ pao - > index ] = * pao ;
hpios_dsplock_init ( & adapters . adapter [ pao - > index ] ) ;
adapters . gw_num_adapters + + ;
unlock :
2011-02-10 07:25:58 +03:00
hpios_alistlock_unlock ( & adapters ) ;
2010-04-21 20:17:39 +04:00
return retval ;
}
void hpi_delete_adapter ( struct hpi_adapter_obj * pao )
{
2011-12-22 04:38:43 +04:00
if ( ! pao - > type ) {
2011-02-10 07:25:58 +03:00
HPI_DEBUG_LOG ( ERROR , " removing null adapter? \n " ) ;
return ;
}
2010-04-21 20:17:39 +04:00
hpios_alistlock_lock ( & adapters ) ;
2011-12-22 04:38:43 +04:00
if ( adapters . adapter [ pao - > index ] . type )
2011-02-10 07:25:58 +03:00
adapters . gw_num_adapters - - ;
memset ( & adapters . adapter [ pao - > index ] , 0 , sizeof ( adapters . adapter [ 0 ] ) ) ;
hpios_alistlock_unlock ( & adapters ) ;
2010-04-21 20:17:39 +04:00
}
/**
2020-07-02 22:35:45 +03:00
* hpi_find_adapter - FindAdapter returns a pointer to the struct
* hpi_adapter_obj with index wAdapterIndex in an HPI_ADAPTERS_LIST
* structure .
* @ adapter_index : value in [ 0 , HPI_MAX_ADAPTERS [
*/
2010-04-21 20:17:39 +04:00
struct hpi_adapter_obj * hpi_find_adapter ( u16 adapter_index )
{
struct hpi_adapter_obj * pao = NULL ;
if ( adapter_index > = HPI_MAX_ADAPTERS ) {
2011-02-10 07:26:02 +03:00
HPI_DEBUG_LOG ( VERBOSE , " find_adapter invalid index %d \n " ,
2010-04-21 20:17:39 +04:00
adapter_index ) ;
return NULL ;
}
pao = & adapters . adapter [ adapter_index ] ;
2011-12-22 04:38:43 +04:00
if ( pao - > type ! = 0 ) {
2010-04-21 20:17:39 +04:00
/*
HPI_DEBUG_LOG ( VERBOSE , " Found adapter index %d \n " ,
wAdapterIndex ) ;
*/
return pao ;
} else {
/*
HPI_DEBUG_LOG ( VERBOSE , " No adapter index %d \n " ,
wAdapterIndex ) ;
*/
return NULL ;
}
}
/**
2020-07-02 22:35:45 +03:00
* wipe_adapter_list - wipe an HPI_ADAPTERS_LIST structure .
*
*/
2011-02-10 07:25:58 +03:00
static void wipe_adapter_list ( void )
2010-04-21 20:17:39 +04:00
{
memset ( & adapters , 0 , sizeof ( adapters ) ) ;
}
2011-02-10 07:25:58 +03:00
static void subsys_get_adapter ( struct hpi_message * phm ,
struct hpi_response * phr )
2010-04-21 20:17:39 +04:00
{
2011-02-10 07:25:58 +03:00
int count = phm - > obj_index ;
u16 index = 0 ;
2010-04-21 20:17:39 +04:00
2011-02-10 07:25:58 +03:00
/* find the nCount'th nonzero adapter in array */
for ( index = 0 ; index < HPI_MAX_ADAPTERS ; index + + ) {
2011-12-22 04:38:43 +04:00
if ( adapters . adapter [ index ] . type ) {
2011-02-10 07:26:06 +03:00
if ( ! count )
2011-02-10 07:25:58 +03:00
break ;
count - - ;
2010-04-21 20:17:39 +04:00
}
}
2011-02-10 07:25:58 +03:00
if ( index < HPI_MAX_ADAPTERS ) {
phr - > u . s . adapter_index = adapters . adapter [ index ] . index ;
2011-12-22 04:38:43 +04:00
phr - > u . s . adapter_type = adapters . adapter [ index ] . type ;
2011-02-10 07:25:58 +03:00
} else {
phr - > u . s . adapter_index = 0 ;
2011-02-10 07:26:09 +03:00
phr - > u . s . adapter_type = 0 ;
2011-12-22 04:38:43 +04:00
phr - > error = HPI_ERROR_INVALID_OBJ_INDEX ;
2011-02-10 07:25:58 +03:00
}
2010-04-21 20:17:39 +04:00
}
static unsigned int control_cache_alloc_check ( struct hpi_control_cache * pC )
{
unsigned int i ;
int cached = 0 ;
if ( ! pC )
return 0 ;
2011-02-10 07:25:58 +03:00
if ( pC - > init )
return pC - > init ;
if ( ! pC - > p_cache )
return 0 ;
if ( pC - > control_count & & pC - > cache_size_in_bytes ) {
char * p_master_cache ;
unsigned int byte_count = 0 ;
p_master_cache = ( char * ) pC - > p_cache ;
HPI_DEBUG_LOG ( DEBUG , " check %d controls \n " ,
2010-04-21 20:17:39 +04:00
pC - > control_count ) ;
for ( i = 0 ; i < pC - > control_count ; i + + ) {
struct hpi_control_cache_info * info =
( struct hpi_control_cache_info * )
2011-02-10 07:25:58 +03:00
& p_master_cache [ byte_count ] ;
2014-11-20 06:22:52 +03:00
u16 control_index = info - > control_index ;
if ( control_index > = pC - > control_count ) {
HPI_DEBUG_LOG ( INFO ,
" adap %d control index %d out of range, cache not ready? \n " ,
pC - > adap_idx , control_index ) ;
return 0 ;
}
2011-02-10 07:25:58 +03:00
if ( ! info - > size_in32bit_words ) {
2011-02-10 07:26:06 +03:00
if ( ! i ) {
2011-02-10 07:26:00 +03:00
HPI_DEBUG_LOG ( INFO ,
" adap %d cache not ready? \n " ,
pC - > adap_idx ) ;
return 0 ;
}
2011-02-10 07:26:02 +03:00
/* The cache is invalid.
* Minimum valid entry size is
* sizeof ( struct hpi_control_cache_info )
*/
2011-02-10 07:25:58 +03:00
HPI_DEBUG_LOG ( ERROR ,
2011-02-10 07:26:00 +03:00
" adap %d zero size cache entry %d \n " ,
pC - > adap_idx , i ) ;
2011-02-10 07:25:58 +03:00
break ;
}
2010-04-21 20:17:39 +04:00
if ( info - > control_type ) {
2014-11-20 06:22:52 +03:00
pC - > p_info [ control_index ] = info ;
2010-04-21 20:17:39 +04:00
cached + + ;
2011-04-05 12:55:48 +04:00
} else { /* dummy cache entry */
2014-11-20 06:22:52 +03:00
pC - > p_info [ control_index ] = NULL ;
2011-04-05 12:55:48 +04:00
}
2010-04-21 20:17:39 +04:00
2011-02-10 07:25:58 +03:00
byte_count + = info - > size_in32bit_words * 4 ;
2010-04-21 20:17:39 +04:00
HPI_DEBUG_LOG ( VERBOSE ,
2011-02-10 07:25:58 +03:00
" cached %d, pinfo %p index %d type %d size %d \n " ,
cached , pC - > p_info [ info - > control_index ] ,
info - > control_index , info - > control_type ,
info - > size_in32bit_words ) ;
2011-02-10 07:26:02 +03:00
/* quit loop early if whole cache has been scanned.
* dwControlCount is the maximum possible entries
* but some may be absent from the cache
*/
2011-02-10 07:25:58 +03:00
if ( byte_count > = pC - > cache_size_in_bytes )
break ;
/* have seen last control index */
if ( info - > control_index = = pC - > control_count - 1 )
break ;
2010-04-21 20:17:39 +04:00
}
2011-02-10 07:25:58 +03:00
if ( byte_count ! = pC - > cache_size_in_bytes )
HPI_DEBUG_LOG ( WARNING ,
2011-02-10 07:26:02 +03:00
" adap %d bytecount %d != cache size %d \n " ,
2011-02-10 07:26:00 +03:00
pC - > adap_idx , byte_count ,
2011-02-10 07:25:58 +03:00
pC - > cache_size_in_bytes ) ;
else
HPI_DEBUG_LOG ( DEBUG ,
2011-02-10 07:26:02 +03:00
" adap %d cache good, bytecount == cache size = %d \n " ,
2011-02-10 07:26:00 +03:00
pC - > adap_idx , byte_count ) ;
2011-02-10 07:25:58 +03:00
2011-02-10 07:26:02 +03:00
pC - > init = ( u16 ) cached ;
2010-04-21 20:17:39 +04:00
}
return pC - > init ;
}
/** Find a control.
*/
2011-02-10 07:25:58 +03:00
static short find_control ( u16 control_index ,
struct hpi_control_cache * p_cache , struct hpi_control_cache_info * * pI )
2010-04-21 20:17:39 +04:00
{
if ( ! control_cache_alloc_check ( p_cache ) ) {
HPI_DEBUG_LOG ( VERBOSE ,
2011-02-10 07:25:58 +03:00
" control_cache_alloc_check() failed %d \n " ,
control_index ) ;
2010-04-21 20:17:39 +04:00
return 0 ;
}
2011-02-10 07:25:58 +03:00
* pI = p_cache - > p_info [ control_index ] ;
2010-04-21 20:17:39 +04:00
if ( ! * pI ) {
2011-02-10 07:25:58 +03:00
HPI_DEBUG_LOG ( VERBOSE , " Uncached Control %d \n " ,
control_index ) ;
2010-04-21 20:17:39 +04:00
return 0 ;
} else {
HPI_DEBUG_LOG ( VERBOSE , " find_control() type %d \n " ,
( * pI ) - > control_type ) ;
}
return 1 ;
}
/* allow unified treatment of several string fields within struct */
# define HPICMN_PAD_OFS_AND_SIZE(m) {\
offsetof ( struct hpi_control_cache_pad , m ) , \
sizeof ( ( ( struct hpi_control_cache_pad * ) ( NULL ) ) - > m ) }
struct pad_ofs_size {
unsigned int offset ;
unsigned int field_size ;
} ;
2011-04-05 12:55:48 +04:00
static const struct pad_ofs_size pad_desc [ ] = {
2010-04-21 20:17:39 +04:00
HPICMN_PAD_OFS_AND_SIZE ( c_channel ) , /* HPI_PAD_CHANNEL_NAME */
HPICMN_PAD_OFS_AND_SIZE ( c_artist ) , /* HPI_PAD_ARTIST */
HPICMN_PAD_OFS_AND_SIZE ( c_title ) , /* HPI_PAD_TITLE */
HPICMN_PAD_OFS_AND_SIZE ( c_comment ) , /* HPI_PAD_COMMENT */
} ;
/** CheckControlCache checks the cache and fills the struct hpi_response
* accordingly . It returns one if a cache hit occurred , zero otherwise .
*/
2014-11-20 06:22:52 +03:00
short hpi_check_control_cache_single ( struct hpi_control_cache_single * pC ,
2010-04-21 20:17:39 +04:00
struct hpi_message * phm , struct hpi_response * phr )
{
2011-07-22 07:52:58 +04:00
size_t response_size ;
2014-11-20 06:22:52 +03:00
short found = 1 ;
2010-04-21 20:17:39 +04:00
2011-07-22 07:52:38 +04:00
/* set the default response size */
response_size =
sizeof ( struct hpi_response_header ) +
sizeof ( struct hpi_control_res ) ;
2014-11-20 06:22:52 +03:00
switch ( pC - > u . i . control_type ) {
2010-04-21 20:17:39 +04:00
case HPI_CONTROL_METER :
if ( phm - > u . c . attribute = = HPI_METER_PEAK ) {
2011-02-10 07:25:58 +03:00
phr - > u . c . an_log_value [ 0 ] = pC - > u . meter . an_log_peak [ 0 ] ;
phr - > u . c . an_log_value [ 1 ] = pC - > u . meter . an_log_peak [ 1 ] ;
2010-04-21 20:17:39 +04:00
} else if ( phm - > u . c . attribute = = HPI_METER_RMS ) {
2011-02-10 07:25:58 +03:00
if ( pC - > u . meter . an_logRMS [ 0 ] = =
HPI_CACHE_INVALID_SHORT ) {
phr - > error =
HPI_ERROR_INVALID_CONTROL_ATTRIBUTE ;
phr - > u . c . an_log_value [ 0 ] = HPI_METER_MINIMUM ;
phr - > u . c . an_log_value [ 1 ] = HPI_METER_MINIMUM ;
} else {
phr - > u . c . an_log_value [ 0 ] =
pC - > u . meter . an_logRMS [ 0 ] ;
phr - > u . c . an_log_value [ 1 ] =
pC - > u . meter . an_logRMS [ 1 ] ;
}
2010-04-21 20:17:39 +04:00
} else
found = 0 ;
break ;
case HPI_CONTROL_VOLUME :
if ( phm - > u . c . attribute = = HPI_VOLUME_GAIN ) {
2011-02-10 07:25:58 +03:00
phr - > u . c . an_log_value [ 0 ] = pC - > u . vol . an_log [ 0 ] ;
phr - > u . c . an_log_value [ 1 ] = pC - > u . vol . an_log [ 1 ] ;
2011-02-10 07:26:11 +03:00
} else if ( phm - > u . c . attribute = = HPI_VOLUME_MUTE ) {
if ( pC - > u . vol . flags & HPI_VOLUME_FLAG_HAS_MUTE ) {
if ( pC - > u . vol . flags & HPI_VOLUME_FLAG_MUTED )
phr - > u . c . param1 =
HPI_BITMASK_ALL_CHANNELS ;
else
phr - > u . c . param1 = 0 ;
} else {
phr - > error =
HPI_ERROR_INVALID_CONTROL_ATTRIBUTE ;
phr - > u . c . param1 = 0 ;
}
} else {
2010-04-21 20:17:39 +04:00
found = 0 ;
2011-02-10 07:26:11 +03:00
}
2010-04-21 20:17:39 +04:00
break ;
case HPI_CONTROL_MULTIPLEXER :
if ( phm - > u . c . attribute = = HPI_MULTIPLEXER_SOURCE ) {
2011-02-10 07:25:58 +03:00
phr - > u . c . param1 = pC - > u . mux . source_node_type ;
phr - > u . c . param2 = pC - > u . mux . source_node_index ;
2010-04-21 20:17:39 +04:00
} else {
found = 0 ;
}
break ;
case HPI_CONTROL_CHANNEL_MODE :
if ( phm - > u . c . attribute = = HPI_CHANNEL_MODE_MODE )
2011-02-10 07:25:58 +03:00
phr - > u . c . param1 = pC - > u . mode . mode ;
2010-04-21 20:17:39 +04:00
else
found = 0 ;
break ;
case HPI_CONTROL_LEVEL :
if ( phm - > u . c . attribute = = HPI_LEVEL_GAIN ) {
2011-02-10 07:25:58 +03:00
phr - > u . c . an_log_value [ 0 ] = pC - > u . level . an_log [ 0 ] ;
phr - > u . c . an_log_value [ 1 ] = pC - > u . level . an_log [ 1 ] ;
2010-04-21 20:17:39 +04:00
} else
found = 0 ;
break ;
case HPI_CONTROL_TUNER :
2010-05-27 09:53:55 +04:00
if ( phm - > u . c . attribute = = HPI_TUNER_FREQ )
2011-02-10 07:25:58 +03:00
phr - > u . c . param1 = pC - > u . tuner . freq_ink_hz ;
2010-05-27 09:53:55 +04:00
else if ( phm - > u . c . attribute = = HPI_TUNER_BAND )
2011-02-10 07:25:58 +03:00
phr - > u . c . param1 = pC - > u . tuner . band ;
else if ( phm - > u . c . attribute = = HPI_TUNER_LEVEL_AVG )
if ( pC - > u . tuner . s_level_avg = =
HPI_CACHE_INVALID_SHORT ) {
phr - > u . cu . tuner . s_level = 0 ;
2010-07-06 00:37:10 +04:00
phr - > error =
HPI_ERROR_INVALID_CONTROL_ATTRIBUTE ;
} else
2011-02-10 07:25:58 +03:00
phr - > u . cu . tuner . s_level =
pC - > u . tuner . s_level_avg ;
2010-05-27 09:53:55 +04:00
else
found = 0 ;
2010-04-21 20:17:39 +04:00
break ;
case HPI_CONTROL_AESEBU_RECEIVER :
if ( phm - > u . c . attribute = = HPI_AESEBURX_ERRORSTATUS )
phr - > u . c . param1 = pC - > u . aes3rx . error_status ;
else if ( phm - > u . c . attribute = = HPI_AESEBURX_FORMAT )
2011-02-10 07:25:58 +03:00
phr - > u . c . param1 = pC - > u . aes3rx . format ;
2010-04-21 20:17:39 +04:00
else
found = 0 ;
break ;
case HPI_CONTROL_AESEBU_TRANSMITTER :
if ( phm - > u . c . attribute = = HPI_AESEBUTX_FORMAT )
phr - > u . c . param1 = pC - > u . aes3tx . format ;
else
found = 0 ;
break ;
case HPI_CONTROL_TONEDETECTOR :
if ( phm - > u . c . attribute = = HPI_TONEDETECTOR_STATE )
phr - > u . c . param1 = pC - > u . tone . state ;
else
found = 0 ;
break ;
case HPI_CONTROL_SILENCEDETECTOR :
if ( phm - > u . c . attribute = = HPI_SILENCEDETECTOR_STATE ) {
phr - > u . c . param1 = pC - > u . silence . state ;
} else
found = 0 ;
break ;
case HPI_CONTROL_MICROPHONE :
if ( phm - > u . c . attribute = = HPI_MICROPHONE_PHANTOM_POWER )
2011-02-10 07:25:58 +03:00
phr - > u . c . param1 = pC - > u . microphone . phantom_state ;
2010-04-21 20:17:39 +04:00
else
found = 0 ;
break ;
case HPI_CONTROL_SAMPLECLOCK :
if ( phm - > u . c . attribute = = HPI_SAMPLECLOCK_SOURCE )
phr - > u . c . param1 = pC - > u . clk . source ;
else if ( phm - > u . c . attribute = = HPI_SAMPLECLOCK_SOURCE_INDEX ) {
if ( pC - > u . clk . source_index = =
2011-02-10 07:25:58 +03:00
HPI_CACHE_INVALID_UINT16 ) {
2010-04-21 20:17:39 +04:00
phr - > u . c . param1 = 0 ;
2010-07-06 00:37:10 +04:00
phr - > error =
HPI_ERROR_INVALID_CONTROL_ATTRIBUTE ;
2010-04-21 20:17:39 +04:00
} else
phr - > u . c . param1 = pC - > u . clk . source_index ;
} else if ( phm - > u . c . attribute = = HPI_SAMPLECLOCK_SAMPLERATE )
phr - > u . c . param1 = pC - > u . clk . sample_rate ;
else
found = 0 ;
break ;
2011-02-10 07:25:58 +03:00
case HPI_CONTROL_PAD : {
struct hpi_control_cache_pad * p_pad ;
2014-11-20 06:22:52 +03:00
p_pad = ( struct hpi_control_cache_pad * ) pC ;
2010-04-21 20:17:39 +04:00
2011-02-10 07:25:58 +03:00
if ( ! ( p_pad - > field_valid_flags & ( 1 < <
HPI_CTL_ATTR_INDEX ( phm - > u . c .
attribute ) ) ) ) {
2010-04-21 20:17:39 +04:00
phr - > error =
HPI_ERROR_INVALID_CONTROL_ATTRIBUTE ;
break ;
}
2011-02-10 07:25:58 +03:00
if ( phm - > u . c . attribute = = HPI_PAD_PROGRAM_ID )
phr - > u . c . param1 = p_pad - > pI ;
else if ( phm - > u . c . attribute = = HPI_PAD_PROGRAM_TYPE )
phr - > u . c . param1 = p_pad - > pTY ;
else {
unsigned int index =
HPI_CTL_ATTR_INDEX ( phm - > u . c .
attribute ) - 1 ;
unsigned int offset = phm - > u . c . param1 ;
unsigned int pad_string_len , field_size ;
char * pad_string ;
unsigned int tocopy ;
if ( index > ARRAY_SIZE ( pad_desc ) - 1 ) {
phr - > error =
HPI_ERROR_INVALID_CONTROL_ATTRIBUTE ;
break ;
}
pad_string =
( ( char * ) p_pad ) +
pad_desc [ index ] . offset ;
field_size = pad_desc [ index ] . field_size ;
/* Ensure null terminator */
pad_string [ field_size - 1 ] = 0 ;
pad_string_len = strlen ( pad_string ) + 1 ;
if ( offset > pad_string_len ) {
phr - > error =
HPI_ERROR_INVALID_CONTROL_VALUE ;
break ;
}
tocopy = pad_string_len - offset ;
if ( tocopy > sizeof ( phr - > u . cu . chars8 . sz_data ) )
tocopy = sizeof ( phr - > u . cu . chars8 .
sz_data ) ;
memcpy ( phr - > u . cu . chars8 . sz_data ,
& pad_string [ offset ] , tocopy ) ;
phr - > u . cu . chars8 . remaining_chars =
pad_string_len - offset - tocopy ;
2010-04-21 20:17:39 +04:00
}
}
break ;
default :
found = 0 ;
break ;
}
2011-02-10 07:25:58 +03:00
HPI_DEBUG_LOG ( VERBOSE , " %s Adap %d, Ctl %d, Type %d, Attr %d \n " ,
found ? " Cached " : " Uncached " , phm - > adapter_index ,
2014-11-20 06:22:52 +03:00
pC - > u . i . control_index , pC - > u . i . control_type ,
phm - > u . c . attribute ) ;
2010-04-21 20:17:39 +04:00
2011-12-22 04:38:49 +04:00
if ( found ) {
2011-07-22 07:52:58 +04:00
phr - > size = ( u16 ) response_size ;
2011-12-22 04:38:49 +04:00
phr - > type = HPI_TYPE_RESPONSE ;
phr - > object = phm - > object ;
phr - > function = phm - > function ;
}
2010-04-21 20:17:39 +04:00
return found ;
}
2014-11-20 06:22:52 +03:00
short hpi_check_control_cache ( struct hpi_control_cache * p_cache ,
2010-04-21 20:17:39 +04:00
struct hpi_message * phm , struct hpi_response * phr )
{
struct hpi_control_cache_info * pI ;
2011-02-10 07:25:58 +03:00
if ( ! find_control ( phm - > obj_index , p_cache , & pI ) ) {
HPI_DEBUG_LOG ( VERBOSE ,
" HPICMN find_control() failed for adap %d \n " ,
phm - > adapter_index ) ;
2014-11-20 06:22:52 +03:00
return 0 ;
2011-02-10 07:25:58 +03:00
}
2010-04-21 20:17:39 +04:00
2014-11-20 06:22:52 +03:00
phr - > error = 0 ;
phr - > specific_error = 0 ;
phr - > version = 0 ;
return hpi_check_control_cache_single ( ( struct hpi_control_cache_single
* ) pI , phm , phr ) ;
}
/** Updates the cache with Set values.
2010-04-21 20:17:39 +04:00
2014-11-20 06:22:52 +03:00
Only update if no error .
Volume and Level return the limited values in the response , so use these
Multiplexer does so use sent values
*/
void hpi_cmn_control_cache_sync_to_msg_single ( struct hpi_control_cache_single
* pC , struct hpi_message * phm , struct hpi_response * phr )
{
switch ( pC - > u . i . control_type ) {
2010-04-21 20:17:39 +04:00
case HPI_CONTROL_VOLUME :
if ( phm - > u . c . attribute = = HPI_VOLUME_GAIN ) {
2011-02-10 07:25:58 +03:00
pC - > u . vol . an_log [ 0 ] = phr - > u . c . an_log_value [ 0 ] ;
pC - > u . vol . an_log [ 1 ] = phr - > u . c . an_log_value [ 1 ] ;
2011-02-10 07:26:11 +03:00
} else if ( phm - > u . c . attribute = = HPI_VOLUME_MUTE ) {
if ( phm - > u . c . param1 )
pC - > u . vol . flags | = HPI_VOLUME_FLAG_MUTED ;
else
pC - > u . vol . flags & = ~ HPI_VOLUME_FLAG_MUTED ;
2010-04-21 20:17:39 +04:00
}
break ;
case HPI_CONTROL_MULTIPLEXER :
/* mux does not return its setting on Set command. */
if ( phm - > u . c . attribute = = HPI_MULTIPLEXER_SOURCE ) {
2011-02-10 07:25:58 +03:00
pC - > u . mux . source_node_type = ( u16 ) phm - > u . c . param1 ;
pC - > u . mux . source_node_index = ( u16 ) phm - > u . c . param2 ;
2010-04-21 20:17:39 +04:00
}
break ;
case HPI_CONTROL_CHANNEL_MODE :
/* mode does not return its setting on Set command. */
if ( phm - > u . c . attribute = = HPI_CHANNEL_MODE_MODE )
2011-02-10 07:25:58 +03:00
pC - > u . mode . mode = ( u16 ) phm - > u . c . param1 ;
2010-04-21 20:17:39 +04:00
break ;
case HPI_CONTROL_LEVEL :
if ( phm - > u . c . attribute = = HPI_LEVEL_GAIN ) {
2011-02-10 07:25:58 +03:00
pC - > u . vol . an_log [ 0 ] = phr - > u . c . an_log_value [ 0 ] ;
pC - > u . vol . an_log [ 1 ] = phr - > u . c . an_log_value [ 1 ] ;
2010-04-21 20:17:39 +04:00
}
break ;
case HPI_CONTROL_MICROPHONE :
if ( phm - > u . c . attribute = = HPI_MICROPHONE_PHANTOM_POWER )
2011-02-10 07:25:58 +03:00
pC - > u . microphone . phantom_state = ( u16 ) phm - > u . c . param1 ;
2010-04-21 20:17:39 +04:00
break ;
case HPI_CONTROL_AESEBU_TRANSMITTER :
if ( phm - > u . c . attribute = = HPI_AESEBUTX_FORMAT )
pC - > u . aes3tx . format = phm - > u . c . param1 ;
break ;
case HPI_CONTROL_AESEBU_RECEIVER :
if ( phm - > u . c . attribute = = HPI_AESEBURX_FORMAT )
2011-02-10 07:25:58 +03:00
pC - > u . aes3rx . format = phm - > u . c . param1 ;
2010-04-21 20:17:39 +04:00
break ;
case HPI_CONTROL_SAMPLECLOCK :
if ( phm - > u . c . attribute = = HPI_SAMPLECLOCK_SOURCE )
pC - > u . clk . source = ( u16 ) phm - > u . c . param1 ;
else if ( phm - > u . c . attribute = = HPI_SAMPLECLOCK_SOURCE_INDEX )
pC - > u . clk . source_index = ( u16 ) phm - > u . c . param1 ;
else if ( phm - > u . c . attribute = = HPI_SAMPLECLOCK_SAMPLERATE )
pC - > u . clk . sample_rate = phm - > u . c . param1 ;
break ;
default :
break ;
}
}
2014-11-20 06:22:52 +03:00
void hpi_cmn_control_cache_sync_to_msg ( struct hpi_control_cache * p_cache ,
struct hpi_message * phm , struct hpi_response * phr )
{
struct hpi_control_cache_single * pC ;
struct hpi_control_cache_info * pI ;
if ( phr - > error )
return ;
if ( ! find_control ( phm - > obj_index , p_cache , & pI ) ) {
HPI_DEBUG_LOG ( VERBOSE ,
" HPICMN find_control() failed for adap %d \n " ,
phm - > adapter_index ) ;
return ;
}
/* pC is the default cached control strucure.
May be cast to something else in the following switch statement .
*/
pC = ( struct hpi_control_cache_single * ) pI ;
hpi_cmn_control_cache_sync_to_msg_single ( pC , phm , phr ) ;
}
2011-04-05 12:55:48 +04:00
/** Allocate control cache.
\ return Cache pointer , or NULL if allocation fails .
*/
2011-02-10 07:26:06 +03:00
struct hpi_control_cache * hpi_alloc_control_cache ( const u32 control_count ,
const u32 size_in_bytes , u8 * p_dsp_control_buffer )
2010-04-21 20:17:39 +04:00
{
struct hpi_control_cache * p_cache =
kmalloc ( sizeof ( * p_cache ) , GFP_KERNEL ) ;
2010-10-29 23:35:25 +04:00
if ( ! p_cache )
return NULL ;
2011-02-10 07:26:06 +03:00
2014-11-20 06:22:52 +03:00
p_cache - > p_info =
kcalloc ( control_count , sizeof ( * p_cache - > p_info ) , GFP_KERNEL ) ;
2010-10-29 23:35:25 +04:00
if ( ! p_cache - > p_info ) {
kfree ( p_cache ) ;
return NULL ;
}
2014-11-20 06:22:52 +03:00
2010-04-21 20:17:39 +04:00
p_cache - > cache_size_in_bytes = size_in_bytes ;
2011-02-10 07:26:06 +03:00
p_cache - > control_count = control_count ;
p_cache - > p_cache = p_dsp_control_buffer ;
2010-04-21 20:17:39 +04:00
p_cache - > init = 0 ;
return p_cache ;
}
void hpi_free_control_cache ( struct hpi_control_cache * p_cache )
{
2011-02-10 07:25:58 +03:00
if ( p_cache ) {
2010-04-21 20:17:39 +04:00
kfree ( p_cache - > p_info ) ;
kfree ( p_cache ) ;
}
}
static void subsys_message ( struct hpi_message * phm , struct hpi_response * phr )
{
2011-02-10 07:25:58 +03:00
hpi_init_response ( phr , HPI_OBJ_SUBSYSTEM , phm - > function , 0 ) ;
2010-04-21 20:17:39 +04:00
switch ( phm - > function ) {
case HPI_SUBSYS_OPEN :
case HPI_SUBSYS_CLOSE :
case HPI_SUBSYS_DRIVER_UNLOAD :
break ;
case HPI_SUBSYS_DRIVER_LOAD :
wipe_adapter_list ( ) ;
hpios_alistlock_init ( & adapters ) ;
break ;
2011-02-10 07:25:58 +03:00
case HPI_SUBSYS_GET_ADAPTER :
subsys_get_adapter ( phm , phr ) ;
break ;
case HPI_SUBSYS_GET_NUM_ADAPTERS :
phr - > u . s . num_adapters = adapters . gw_num_adapters ;
2010-04-21 20:17:39 +04:00
break ;
case HPI_SUBSYS_CREATE_ADAPTER :
break ;
default :
phr - > error = HPI_ERROR_INVALID_FUNC ;
break ;
}
}
void HPI_COMMON ( struct hpi_message * phm , struct hpi_response * phr )
{
switch ( phm - > type ) {
2011-07-22 07:52:36 +04:00
case HPI_TYPE_REQUEST :
2010-04-21 20:17:39 +04:00
switch ( phm - > object ) {
case HPI_OBJ_SUBSYSTEM :
subsys_message ( phm , phr ) ;
break ;
}
break ;
default :
phr - > error = HPI_ERROR_INVALID_TYPE ;
break ;
}
}