mirror of
https://gitee.com/openharmony/third_party_alsa-lib
synced 2025-02-21 09:10:34 +00:00
test: use actual information for TLV operation
Currently, this test program uses undefined type of TLV data. This can bring confusions to userspace applications. This commit replaces the array with valid information, constructed by newly exported TLV macros from kernel land. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
21dcb000c8
commit
ee1182d2cb
@ -8,6 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../include/asoundlib.h"
|
#include "../include/asoundlib.h"
|
||||||
|
#include <sound/tlv.h>
|
||||||
|
|
||||||
struct elem_set_trial {
|
struct elem_set_trial {
|
||||||
snd_ctl_t *handle;
|
snd_ctl_t *handle;
|
||||||
@ -25,8 +26,30 @@ struct elem_set_trial {
|
|||||||
snd_ctl_elem_info_t *info);
|
snd_ctl_elem_info_t *info);
|
||||||
void (*change_elem_members)(struct elem_set_trial *trial,
|
void (*change_elem_members)(struct elem_set_trial *trial,
|
||||||
snd_ctl_elem_value_t *elem_data);
|
snd_ctl_elem_value_t *elem_data);
|
||||||
|
int (*allocate_elem_set_tlv)(struct elem_set_trial *trial,
|
||||||
|
unsigned int **tlv);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct chmap_entry {
|
||||||
|
unsigned int type;
|
||||||
|
unsigned int length;
|
||||||
|
unsigned int maps[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* History of TLV feature:
|
||||||
|
*
|
||||||
|
* 2016/09/15: 398fa4db6c69 ("ALSA: control: move layout of TLV payload to UAPI
|
||||||
|
* header")
|
||||||
|
* 2012/07/21: 2d3391ec0ecc ("ALSA: PCM: channel mapping API implementation")
|
||||||
|
* 2011/11/20: bf1d1c9b6179 ("ALSA: tlv: add DECLARE_TLV_DB_RANGE()")
|
||||||
|
* 2009/07/16: 085f30654175 ("ALSA: Add new TLV types for dBwith min/max")
|
||||||
|
* 2006/09/06: 55a29af5ed5d ("[ALSA] Add definition of TLV dB range compound")
|
||||||
|
* 2006/08/28: 063a40d9111c ("Add the definition of linear volume TLV")
|
||||||
|
* 2006/08/28: 42750b04c5ba ("[ALSA] Control API - TLV implementation for
|
||||||
|
* additional information like dB scale")
|
||||||
|
*/
|
||||||
|
|
||||||
/* Operations for elements in an element set with boolean type. */
|
/* Operations for elements in an element set with boolean type. */
|
||||||
static int add_bool_elem_set(struct elem_set_trial *trial,
|
static int add_bool_elem_set(struct elem_set_trial *trial,
|
||||||
snd_ctl_elem_info_t *info)
|
snd_ctl_elem_info_t *info)
|
||||||
@ -47,13 +70,30 @@ static void change_bool_elem_members(struct elem_set_trial *trial,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int allocate_bool_elem_set_tlv(struct elem_set_trial *trial,
|
||||||
|
unsigned int **tlv)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Performs like a toggle switch for attenuation, because they're bool
|
||||||
|
* elements.
|
||||||
|
*/
|
||||||
|
static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(range, -10000, 0);
|
||||||
|
|
||||||
|
*tlv = malloc(sizeof(range));
|
||||||
|
if (*tlv == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
memcpy(*tlv, range, sizeof(range));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Operations for elements in an element set with integer type. */
|
/* Operations for elements in an element set with integer type. */
|
||||||
static int add_int_elem_set(struct elem_set_trial *trial,
|
static int add_int_elem_set(struct elem_set_trial *trial,
|
||||||
snd_ctl_elem_info_t *info)
|
snd_ctl_elem_info_t *info)
|
||||||
{
|
{
|
||||||
return snd_ctl_add_integer_elem_set(trial->handle, info,
|
return snd_ctl_add_integer_elem_set(trial->handle, info,
|
||||||
trial->element_count, trial->member_count,
|
trial->element_count, trial->member_count,
|
||||||
0, 99, 1);
|
0, 25, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int check_int_elem_props(struct elem_set_trial *trial,
|
static int check_int_elem_props(struct elem_set_trial *trial,
|
||||||
@ -61,7 +101,7 @@ static int check_int_elem_props(struct elem_set_trial *trial,
|
|||||||
{
|
{
|
||||||
if (snd_ctl_elem_info_get_min(info) != 0)
|
if (snd_ctl_elem_info_get_min(info) != 0)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
if (snd_ctl_elem_info_get_max(info) != 99)
|
if (snd_ctl_elem_info_get_max(info) != 25)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
if (snd_ctl_elem_info_get_step(info) != 1)
|
if (snd_ctl_elem_info_get_step(info) != 1)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
@ -81,6 +121,41 @@ static void change_int_elem_members(struct elem_set_trial *trial,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int allocate_int_elem_set_tlv(struct elem_set_trial *trial,
|
||||||
|
unsigned int **tlv)
|
||||||
|
{
|
||||||
|
unsigned int len, pos;
|
||||||
|
unsigned int i, j;
|
||||||
|
struct chmap_entry *entry;
|
||||||
|
|
||||||
|
/* Calculate size of TLV packet for channel-mapping information. */
|
||||||
|
len = 0;
|
||||||
|
for (i = 1; i <= 25; ++i) {
|
||||||
|
len += sizeof(struct chmap_entry);
|
||||||
|
len += i * sizeof(unsigned int);
|
||||||
|
}
|
||||||
|
|
||||||
|
*tlv = malloc(len);
|
||||||
|
if (*tlv == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Emulate channel-mapping information in in-kernel implementation.
|
||||||
|
* Here, 25 entries are for each different channel.
|
||||||
|
*/
|
||||||
|
pos = 0;
|
||||||
|
for (i = 1; i <= 25 && pos < len; ++i) {
|
||||||
|
entry = (struct chmap_entry *)&(*tlv)[pos];
|
||||||
|
entry->type = SNDRV_CTL_TLVT_CHMAP_FIXED;
|
||||||
|
entry->length = i * sizeof(unsigned int);
|
||||||
|
for (j = 0; j < i; ++j)
|
||||||
|
entry->maps[j] = SND_CHMAP_MONO + j;
|
||||||
|
pos += sizeof(struct chmap_entry) + i * sizeof(unsigned int);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Operations for elements in an element set with enumerated type. */
|
/* Operations for elements in an element set with enumerated type. */
|
||||||
static const char *const labels[] = {
|
static const char *const labels[] = {
|
||||||
"trusty",
|
"trusty",
|
||||||
@ -158,6 +233,24 @@ static void change_bytes_elem_members(struct elem_set_trial *trial,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int allocate_bytes_elem_set_tlv(struct elem_set_trial *trial,
|
||||||
|
unsigned int **tlv)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Emulate AK4396.
|
||||||
|
* 20 * log10(x/255) (dB)
|
||||||
|
* Here, x is written value.
|
||||||
|
*/
|
||||||
|
static const SNDRV_CTL_TLVD_DECLARE_DB_LINEAR(range, -4813, 0);
|
||||||
|
|
||||||
|
*tlv = malloc(sizeof(range));
|
||||||
|
if (*tlv == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
memcpy(*tlv, range, sizeof(range));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Operations for elements in an element set with iec958 type. */
|
/* Operations for elements in an element set with iec958 type. */
|
||||||
static int add_iec958_elem_set(struct elem_set_trial *trial,
|
static int add_iec958_elem_set(struct elem_set_trial *trial,
|
||||||
snd_ctl_elem_info_t *info)
|
snd_ctl_elem_info_t *info)
|
||||||
@ -197,17 +290,17 @@ static int add_int64_elem_set(struct elem_set_trial *trial,
|
|||||||
{
|
{
|
||||||
return snd_ctl_add_integer64_elem_set(trial->handle, info,
|
return snd_ctl_add_integer64_elem_set(trial->handle, info,
|
||||||
trial->element_count, trial->member_count,
|
trial->element_count, trial->member_count,
|
||||||
100, 10000, 30);
|
0, 10000, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int check_int64_elem_props(struct elem_set_trial *trial,
|
static int check_int64_elem_props(struct elem_set_trial *trial,
|
||||||
snd_ctl_elem_info_t *info)
|
snd_ctl_elem_info_t *info)
|
||||||
{
|
{
|
||||||
if (snd_ctl_elem_info_get_min64(info) != 100)
|
if (snd_ctl_elem_info_get_min64(info) != 0)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
if (snd_ctl_elem_info_get_max64(info) != 10000)
|
if (snd_ctl_elem_info_get_max64(info) != 10000)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
if (snd_ctl_elem_info_get_step64(info) != 30)
|
if (snd_ctl_elem_info_get_step64(info) != 1)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -225,6 +318,45 @@ static void change_int64_elem_members(struct elem_set_trial *trial,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int allocate_int64_elem_set_tlv(struct elem_set_trial *trial,
|
||||||
|
unsigned int **tlv)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Use this fomula between linear/dB value:
|
||||||
|
*
|
||||||
|
* Linear: dB range (coeff)
|
||||||
|
* 0<-> 4: -59.40<->-56.36 (44)
|
||||||
|
* 4<->22: -56.36<->-45.56 (60)
|
||||||
|
* 22<->33: -45.56<->-40.72 (76)
|
||||||
|
* 33<->37: -40.72<->-38.32 (44)
|
||||||
|
* 37<->48: -38.32<->-29.96 (76)
|
||||||
|
* 48<->66: -29.96<->-22.04 (60)
|
||||||
|
* 66<->84: -22.04<-> -8.36 (44)
|
||||||
|
* 84<->95: -8.36<-> -1.76 (60)
|
||||||
|
* 95<->99: -1.76<-> 0.00 (76)
|
||||||
|
* 100<->..: 0.0
|
||||||
|
*/
|
||||||
|
static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(range,
|
||||||
|
0, 4, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-5940, 44, 1),
|
||||||
|
4, 22, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-5636, 60, 0),
|
||||||
|
22, 33, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-4556, 76, 0),
|
||||||
|
33, 37, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-4072, 44, 0),
|
||||||
|
37, 48, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-3832, 76, 0),
|
||||||
|
48, 66, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-2996, 60, 0),
|
||||||
|
66, 84, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-2204, 44, 0),
|
||||||
|
84, 95, SNDRV_CTL_TLVD_DB_SCALE_ITEM( -836, 60, 0),
|
||||||
|
95, 99, SNDRV_CTL_TLVD_DB_SCALE_ITEM( -176, 76, 0),
|
||||||
|
100, 10000, SNDRV_CTL_TLVD_DB_SCALE_ITEM(0, 0, 0),
|
||||||
|
);
|
||||||
|
|
||||||
|
*tlv = malloc(sizeof(range));
|
||||||
|
if (*tlv == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
memcpy(*tlv, range, sizeof(range));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Common operations. */
|
/* Common operations. */
|
||||||
static int add_elem_set(struct elem_set_trial *trial)
|
static int add_elem_set(struct elem_set_trial *trial)
|
||||||
{
|
{
|
||||||
@ -414,41 +546,41 @@ static int check_elems(struct elem_set_trial *trial)
|
|||||||
|
|
||||||
static int check_tlv(struct elem_set_trial *trial)
|
static int check_tlv(struct elem_set_trial *trial)
|
||||||
{
|
{
|
||||||
unsigned int orig[8], curr[8];
|
unsigned int *tlv;
|
||||||
|
unsigned int len;
|
||||||
|
unsigned int *curr;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/*
|
err = trial->allocate_elem_set_tlv(trial, &tlv);
|
||||||
* See a layout of 'struct snd_ctl_tlv'. I don't know the reason to
|
if (err < 0)
|
||||||
* construct this buffer with the same layout. It should be abstracted
|
return err;
|
||||||
* inner userspace library...
|
|
||||||
*/
|
len = tlv[1] + sizeof(unsigned int) * 2;
|
||||||
orig[0] = snd_ctl_elem_id_get_numid(trial->id);
|
curr = malloc(len);
|
||||||
orig[1] = 6 * sizeof(orig[0]);
|
if (curr == NULL) {
|
||||||
orig[2] = 'a';
|
free(tlv);
|
||||||
orig[3] = 'b';
|
return -ENOMEM;
|
||||||
orig[4] = 'c';
|
}
|
||||||
orig[5] = 'd';
|
|
||||||
orig[6] = 'e';
|
|
||||||
orig[7] = 'f';
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In in-kernel implementation, write and command operations are the
|
* In in-kernel implementation, write and command operations are the
|
||||||
* same for an element set added by userspace applications. Here, I
|
* same for an element set added by userspace applications. Here, I
|
||||||
* use write.
|
* use write.
|
||||||
*/
|
*/
|
||||||
err = snd_ctl_elem_tlv_write(trial->handle, trial->id,
|
err = snd_ctl_elem_tlv_write(trial->handle, trial->id,
|
||||||
(const unsigned int *)orig);
|
(const unsigned int *)tlv);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
goto end;
|
||||||
|
|
||||||
err = snd_ctl_elem_tlv_read(trial->handle, trial->id, curr,
|
err = snd_ctl_elem_tlv_read(trial->handle, trial->id, curr, len);
|
||||||
sizeof(curr));
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
goto end;
|
||||||
|
|
||||||
if (memcmp(curr, orig, sizeof(orig)) != 0)
|
|
||||||
return -EIO;
|
|
||||||
|
|
||||||
|
if (memcmp(curr, tlv, len) != 0)
|
||||||
|
err = -EIO;
|
||||||
|
end:
|
||||||
|
free(tlv);
|
||||||
|
free(curr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -484,6 +616,8 @@ int main(void)
|
|||||||
trial.add_elem_set = add_bool_elem_set;
|
trial.add_elem_set = add_bool_elem_set;
|
||||||
trial.check_elem_props = NULL;
|
trial.check_elem_props = NULL;
|
||||||
trial.change_elem_members = change_bool_elem_members;
|
trial.change_elem_members = change_bool_elem_members;
|
||||||
|
trial.allocate_elem_set_tlv =
|
||||||
|
allocate_bool_elem_set_tlv;
|
||||||
break;
|
break;
|
||||||
case SND_CTL_ELEM_TYPE_INTEGER:
|
case SND_CTL_ELEM_TYPE_INTEGER:
|
||||||
trial.element_count = 900;
|
trial.element_count = 900;
|
||||||
@ -495,6 +629,8 @@ int main(void)
|
|||||||
trial.add_elem_set = add_int_elem_set;
|
trial.add_elem_set = add_int_elem_set;
|
||||||
trial.check_elem_props = check_int_elem_props;
|
trial.check_elem_props = check_int_elem_props;
|
||||||
trial.change_elem_members = change_int_elem_members;
|
trial.change_elem_members = change_int_elem_members;
|
||||||
|
trial.allocate_elem_set_tlv =
|
||||||
|
allocate_int_elem_set_tlv;
|
||||||
break;
|
break;
|
||||||
case SND_CTL_ELEM_TYPE_ENUMERATED:
|
case SND_CTL_ELEM_TYPE_ENUMERATED:
|
||||||
trial.element_count = 900;
|
trial.element_count = 900;
|
||||||
@ -506,6 +642,7 @@ int main(void)
|
|||||||
trial.add_elem_set = add_enum_elem_set;
|
trial.add_elem_set = add_enum_elem_set;
|
||||||
trial.check_elem_props = check_enum_elem_props;
|
trial.check_elem_props = check_enum_elem_props;
|
||||||
trial.change_elem_members = change_enum_elem_members;
|
trial.change_elem_members = change_enum_elem_members;
|
||||||
|
trial.allocate_elem_set_tlv = NULL;
|
||||||
break;
|
break;
|
||||||
case SND_CTL_ELEM_TYPE_BYTES:
|
case SND_CTL_ELEM_TYPE_BYTES:
|
||||||
trial.element_count = 900;
|
trial.element_count = 900;
|
||||||
@ -517,6 +654,8 @@ int main(void)
|
|||||||
trial.add_elem_set = add_bytes_elem_set;
|
trial.add_elem_set = add_bytes_elem_set;
|
||||||
trial.check_elem_props = NULL;
|
trial.check_elem_props = NULL;
|
||||||
trial.change_elem_members = change_bytes_elem_members;
|
trial.change_elem_members = change_bytes_elem_members;
|
||||||
|
trial.allocate_elem_set_tlv =
|
||||||
|
allocate_bytes_elem_set_tlv;
|
||||||
break;
|
break;
|
||||||
case SND_CTL_ELEM_TYPE_IEC958:
|
case SND_CTL_ELEM_TYPE_IEC958:
|
||||||
trial.element_count = 1;
|
trial.element_count = 1;
|
||||||
@ -528,6 +667,7 @@ int main(void)
|
|||||||
trial.add_elem_set = add_iec958_elem_set;
|
trial.add_elem_set = add_iec958_elem_set;
|
||||||
trial.check_elem_props = NULL;
|
trial.check_elem_props = NULL;
|
||||||
trial.change_elem_members = change_iec958_elem_members;
|
trial.change_elem_members = change_iec958_elem_members;
|
||||||
|
trial.allocate_elem_set_tlv = NULL;
|
||||||
break;
|
break;
|
||||||
case SND_CTL_ELEM_TYPE_INTEGER64:
|
case SND_CTL_ELEM_TYPE_INTEGER64:
|
||||||
default:
|
default:
|
||||||
@ -540,6 +680,8 @@ int main(void)
|
|||||||
trial.add_elem_set = add_int64_elem_set;
|
trial.add_elem_set = add_int64_elem_set;
|
||||||
trial.check_elem_props = check_int64_elem_props;
|
trial.check_elem_props = check_int64_elem_props;
|
||||||
trial.change_elem_members = change_int64_elem_members;
|
trial.change_elem_members = change_int64_elem_members;
|
||||||
|
trial.allocate_elem_set_tlv =
|
||||||
|
allocate_int64_elem_set_tlv;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -589,22 +731,22 @@ int main(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Test an operation to change threshold data of this element set,
|
* Test an operation to change TLV data of this element set,
|
||||||
* except for IEC958 type.
|
* except for enumerated and IEC958 type.
|
||||||
*/
|
*/
|
||||||
if (trial.type != SND_CTL_ELEM_TYPE_IEC958) {
|
if (trial.allocate_elem_set_tlv != NULL) {
|
||||||
err = check_tlv(&trial);
|
err = check_tlv(&trial);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
printf("Fail to change threshold level of an "
|
printf("Fail to change TLV data of an element "
|
||||||
"element set with %s type.\n",
|
"set with %s type.\n",
|
||||||
snd_ctl_elem_type_name(trial.type));
|
snd_ctl_elem_type_name(trial.type));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
err = check_event(&trial, SND_CTL_EVENT_MASK_TLV, 1);
|
err = check_event(&trial, SND_CTL_EVENT_MASK_TLV, 1);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
printf("Fail to check an event to change "
|
printf("Fail to check an event to change TLV"
|
||||||
"threshold level of an an element set "
|
"data of an an element set with %s "
|
||||||
"with %s type.\n",
|
"type.\n",
|
||||||
snd_ctl_elem_type_name(trial.type));
|
snd_ctl_elem_type_name(trial.type));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user