aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2011-05-27 16:24:15 +0200
committerTakashi Iwai <tiwai@suse.de>2011-05-27 16:24:15 +0200
commit0ee5f47624ac97fdae56d6c79e19a9324b729fa0 (patch)
tree5398baa561e0b17dcd84253cd64ea9c00f52eb36
parent7fb12ca79b96d791119c20a5a3ad4d14fd97b49e (diff)
downloadsalsa-lib-0ee5f47624ac97fdae56d6c79e19a9324b729fa0.tar.gz
Define the correct version of snd_tlv_parse_dB_info()
-rw-r--r--src/control.c42
-rw-r--r--src/ctl_func.h3
-rw-r--r--src/ctl_macros.h11
-rw-r--r--src/mixer.c74
4 files changed, 53 insertions, 77 deletions
diff --git a/src/control.c b/src/control.c
index 0d53f05..522f986 100644
--- a/src/control.c
+++ b/src/control.c
@@ -355,6 +355,48 @@ int snd_async_add_ctl_handler(snd_async_handler_t **handler, snd_ctl_t *ctl,
/* max size of a TLV entry for dB information (including compound one) */
#define MAX_TLV_RANGE_SIZE 256
+/* parse dB info from the given TLV */
+int snd_tlv_parse_dB_info(unsigned int *tlv,
+ unsigned int tlv_size,
+ unsigned int **db_tlvp)
+{
+ unsigned int type;
+ unsigned int size;
+ int err;
+
+ *db_tlvp = NULL;
+ type = tlv[0];
+ size = tlv[1];
+ tlv_size -= 2 * sizeof(int);
+ if (size > tlv_size)
+ return -EINVAL;
+ switch (type) {
+ case SND_CTL_TLVT_CONTAINER:
+ size = int_index(size) * sizeof(int);
+ tlv += 2;
+ while (size > 0) {
+ unsigned int len;
+ err = snd_tlv_parse_dB_info(tlv, size, db_tlvp);
+ if (err != 0)
+ return err;
+ len = int_index(tlv[1]) + 2;
+ size -= len * sizeof(int);
+ tlv += len;
+ }
+ return -EINVAL;
+ case SND_CTL_TLVT_DB_SCALE:
+ case SND_CTL_TLVT_DB_MINMAX:
+ case SND_CTL_TLVT_DB_MINMAX_MUTE:
+#if SALSA_SUPPORT_FLOAT
+ case SND_CTL_TLVT_DB_LINEAR:
+#endif
+ case SND_CTL_TLVT_DB_RANGE:
+ *db_tlvp = tlv;
+ return size + sizeof(int) * 2;
+ }
+ return 0;
+}
+
/* convert the given raw volume value to a dB gain
*/
static int tlv_to_dB_range(unsigned int *tlv, long rangemin, long rangemax,
diff --git a/src/ctl_func.h b/src/ctl_func.h
index 491735e..87ff259 100644
--- a/src/ctl_func.h
+++ b/src/ctl_func.h
@@ -56,6 +56,9 @@ int snd_ctl_elem_add_boolean(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id,
int snd_ctl_elem_add_iec958(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id);
#if SALSA_HAS_TLV_SUPPORT
+int snd_tlv_parse_dB_info(unsigned int *tlv,
+ unsigned int tlv_size,
+ unsigned int **db_tlvp);
int snd_tlv_get_dB_range(unsigned int *tlv, long rangemin, long rangemax,
long *min, long *max);
int snd_tlv_convert_to_dB(unsigned int *tlv, long rangemin, long rangemax,
diff --git a/src/ctl_macros.h b/src/ctl_macros.h
index 239ecec..fae15c0 100644
--- a/src/ctl_macros.h
+++ b/src/ctl_macros.h
@@ -1076,15 +1076,4 @@ snd_ctl_t *snd_async_handler_get_ctl(snd_async_handler_t *handler)
#endif /* SALSA_HAS_ASYNC_SUPPORT */
-#if SALSA_HAS_TLV_SUPPORT
-__SALSA_EXPORT_FUNC
-int snd_tlv_parse_dB_info(unsigned int *tlv, unsigned int tlv_size,
- unsigned int **db_tlvp)
-{
- /* just for simplicity */
- *db_tlvp = tlv;
- return 0;
-}
-#endif /* SALSA_HAS_TLV_SUPPORT */
-
#endif /* __ALSA_CTL_MACROS_H */
diff --git a/src/mixer.c b/src/mixer.c
index 4c12476..11ac673 100644
--- a/src/mixer.c
+++ b/src/mixer.c
@@ -1004,71 +1004,8 @@ int snd_mixer_selem_set_enum_item(snd_mixer_elem_t *elem,
#if SALSA_HAS_TLV_SUPPORT
-
-/* convert to index of integer array */
-#define int_index(size) (((size) + sizeof(int) - 1) / sizeof(int))
-
-/* max size of a TLV entry for dB information (including compound one) */
-#define MAX_TLV_RANGE_SIZE 256
-
-/* parse TLV stream and retrieve dB information
- * return 0 if successly found and stored to rec,
- * return 1 if no information is found,
- * or return a negative error code
- */
-static int parse_db_range(snd_selem_vol_item_t *item, unsigned int *tlv,
- unsigned int tlv_size)
-{
- unsigned int type;
- unsigned int size;
- int err;
-
- type = tlv[0];
- size = tlv[1];
- tlv_size -= 2 * sizeof(int);
- if (size > tlv_size)
- return -EINVAL;
- switch (type) {
- case SND_CTL_TLVT_CONTAINER:
- size = int_index(size) * sizeof(int);
- tlv += 2;
- while (size > 0) {
- unsigned int len;
- err = parse_db_range(item, tlv, size);
- if (err <= 0)
- return err; /* error or found dB */
- len = int_index(tlv[1]) + 2;
- size -= len * sizeof(int);
- tlv += len;
- }
- break;
- case SND_CTL_TLVT_DB_SCALE:
- case SND_CTL_TLVT_DB_RANGE: {
- unsigned int minsize;
- if (type == SND_CTL_TLVT_DB_RANGE)
- minsize = 4 * sizeof(int);
- else
- minsize = 2 * sizeof(int);
- if (size < minsize)
- return -EINVAL;
- if (size > MAX_TLV_RANGE_SIZE)
- return -EINVAL;
- item->db_info = malloc(size + sizeof(int) * 2);
- if (!item->db_info)
- return -ENOMEM;
- memcpy(item->db_info, tlv, size + sizeof(int) * 2);
- return 0;
- }
- default:
- break;
- }
- return -EINVAL; /* not found */
-}
-
/*
* dB conversion
- *
- * For simplicity, we don't support the linear - log conversion
*/
/* initialize dB range information, reading TLV via hcontrol
@@ -1078,6 +1015,7 @@ static int init_db_info(snd_selem_vol_item_t *item)
snd_ctl_elem_info_t *info;
unsigned int *tlv = NULL;
const unsigned int tlv_size = 4096;
+ int size;
if (!item)
return -EINVAL;
@@ -1091,11 +1029,16 @@ static int init_db_info(snd_selem_vol_item_t *item)
goto error;
tlv = malloc(tlv_size);
if (!tlv)
- return -ENOMEM;
+ goto error;
if (snd_hctl_elem_tlv_read(item->head.helem, tlv, tlv_size) < 0)
goto error;
- if (parse_db_range(item, tlv, tlv_size) < 0)
+ size = snd_tlv_parse_dB_info(tlv, tlv_size, &tlv);
+ if (size <= 0)
+ goto error;
+ item->db_info = malloc(size);
+ if (!item->db_info)
goto error;
+ memcpy(item->db_info, tlv, size);
free(tlv);
return 0;
@@ -1105,7 +1048,6 @@ static int init_db_info(snd_selem_vol_item_t *item)
return -EINVAL;
}
-
int _snd_selem_vol_get_dB(snd_selem_vol_item_t *item, int channel,
long *value)
{