[alsa-devel] [alsa-lib][PATCH 0/6] control: optimization for position offset macro of TLV data
Hi,
In development period for Linux v4.18, a series of SNDRV_CTL_TLVO_XXX macro was introduced to kernel stuffs for position offset of TLV data.
This patchset backports the macros to this library as well as adds code optimization with them.
Takashi Sakamoto (6): control: add a series of macro for offset of several types of TLV control: use position offset macro of TLV data hcontrol: use position offset macro of TLV data pcm: hw: use position offset macro of TLV data pcm: softvol: use position offset macro of TLV data test: use position offset macro of TLV data
include/sound/tlv.h | 16 ++++++++++ src/control/control.c | 12 ++++---- src/control/control_hw.c | 6 ++-- src/control/control_local.h | 1 + src/control/hcontrol.c | 4 +-- src/control/tlv.c | 72 ++++++++++++++++++++++++--------------------- src/pcm/pcm_hw.c | 10 ++++--- src/pcm/pcm_softvol.c | 11 ++++--- test/user-ctl-element-set.c | 2 +- 9 files changed, 83 insertions(+), 51 deletions(-)
In development period for Linux v4.18, a series of SNDRV_CTL_TLVO_XXX macro was introduced to kernel stuffs for position offset of TLV data.
This commit adds these macros to backport header in this library.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- include/sound/tlv.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/include/sound/tlv.h b/include/sound/tlv.h index b4df440c..2ea47685 100644 --- a/include/sound/tlv.h +++ b/include/sound/tlv.h @@ -41,6 +41,10 @@ #define SNDRV_CTL_TLVD_LENGTH(...) \ ((unsigned int)sizeof((const unsigned int[]) { __VA_ARGS__ }))
+/* Accessor offsets for TLV data items */ +#define SNDRV_CTL_TLVO_TYPE 0 +#define SNDRV_CTL_TLVO_LEN 1 + #define SNDRV_CTL_TLVD_CONTAINER_ITEM(...) \ SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_CONTAINER, __VA_ARGS__) #define SNDRV_CTL_TLVD_DECLARE_CONTAINER(name, ...) \ @@ -60,6 +64,10 @@ SNDRV_CTL_TLVD_DB_SCALE_ITEM(min, step, mute) \ }
+/* Accessor offsets for min, mute and step items in dB scale type TLV */ +#define SNDRV_CTL_TLVO_DB_SCALE_MIN 2 +#define SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP 3 + /* dB scale specified with min/max values instead of step */ #define SNDRV_CTL_TLVD_DB_MINMAX_ITEM(min_dB, max_dB) \ SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_MINMAX, (min_dB), (max_dB)) @@ -74,6 +82,10 @@ SNDRV_CTL_TLVD_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) \ }
+/* Accessor offsets for min, max items in db-minmax types of TLV. */ +#define SNDRV_CTL_TLVO_DB_MINMAX_MIN 2 +#define SNDRV_CTL_TLVO_DB_MINMAX_MAX 3 + /* linear volume between min_dB and max_dB (.01dB unit) */ #define SNDRV_CTL_TLVD_DB_LINEAR_ITEM(min_dB, max_dB) \ SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_LINEAR, (min_dB), (max_dB)) @@ -82,6 +94,10 @@ SNDRV_CTL_TLVD_DB_LINEAR_ITEM(min_dB, max_dB) \ }
+/* Accessor offsets for min, max items in db-linear type of TLV. */ +#define SNDRV_CTL_TLVO_DB_LINEAR_MIN 2 +#define SNDRV_CTL_TLVO_DB_LINEAR_MAX 3 + /* dB range container: * Items in dB range container must be ordered by their values and by their * dB values. This implies that larger values must correspond with larger
A series of SNDRV_CTL_TLVO_XXX macro was introduced for position offset of TLV data. This commit applies a code optimization.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- src/control/control.c | 12 ++++---- src/control/control_hw.c | 6 ++-- src/control/control_local.h | 1 + src/control/tlv.c | 72 ++++++++++++++++++++++++--------------------- 4 files changed, 51 insertions(+), 40 deletions(-)
diff --git a/src/control/control.c b/src/control/control.c index 11f7815a..82cd1a05 100644 --- a/src/control/control.c +++ b/src/control/control.c @@ -938,10 +938,10 @@ int snd_ctl_elem_tlv_read(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, * and compare the returned value after ioctl for checking * the validity of TLV. */ - tlv[0] = -1; - tlv[1] = 0; + tlv[SNDRV_CTL_TLVO_TYPE] = -1; + tlv[SNDRV_CTL_TLVO_LEN] = 0; err = snd_ctl_tlv_do(ctl, 0, id, tlv, tlv_size); - if (err >= 0 && tlv[0] == (unsigned int)-1) + if (err >= 0 && tlv[SNDRV_CTL_TLVO_TYPE] == (unsigned int)-1) err = -ENXIO; return err; } @@ -967,7 +967,8 @@ int snd_ctl_elem_tlv_write(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, const unsigned int *tlv) { assert(ctl && id && (id->name[0] || id->numid) && tlv); - return snd_ctl_tlv_do(ctl, 1, id, (unsigned int *)tlv, tlv[1] + 2 * sizeof(unsigned int)); + return snd_ctl_tlv_do(ctl, 1, id, (unsigned int *)tlv, + tlv[SNDRV_CTL_TLVO_LEN] + 2 * sizeof(unsigned int)); }
/** @@ -991,7 +992,8 @@ int snd_ctl_elem_tlv_command(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, const unsigned int *tlv) { assert(ctl && id && (id->name[0] || id->numid) && tlv); - return snd_ctl_tlv_do(ctl, -1, id, (unsigned int *)tlv, tlv[1] + 2 * sizeof(unsigned int)); + return snd_ctl_tlv_do(ctl, -1, id, (unsigned int *)tlv, + tlv[SNDRV_CTL_TLVO_LEN] + 2 * sizeof(unsigned int)); }
/** diff --git a/src/control/control_hw.c b/src/control/control_hw.c index 4cbd306f..68eca522 100644 --- a/src/control/control_hw.c +++ b/src/control/control_hw.c @@ -240,11 +240,13 @@ static int snd_ctl_hw_elem_tlv(snd_ctl_t *handle, int op_flag, return -errno; } if (op_flag == 0) { - if (xtlv->tlv[1] + 2 * sizeof(unsigned int) > tlv_size) { + unsigned int size; + size = xtlv->tlv[SNDRV_CTL_TLVO_LEN] + 2 * sizeof(unsigned int); + if (size > tlv_size) { free(xtlv); return -EFAULT; } - memcpy(tlv, xtlv->tlv, xtlv->tlv[1] + 2 * sizeof(unsigned int)); + memcpy(tlv, xtlv->tlv, size); } free(xtlv); return 0; diff --git a/src/control/control_local.h b/src/control/control_local.h index 30218c6c..9568968e 100644 --- a/src/control/control_local.h +++ b/src/control/control_local.h @@ -20,6 +20,7 @@ */
#include "local.h" +#include <sound/tlv.h>
typedef struct _snd_ctl_ops { int (*close)(snd_ctl_t *handle); diff --git a/src/control/tlv.c b/src/control/tlv.c index 467023b3..d6944b52 100644 --- a/src/control/tlv.c +++ b/src/control/tlv.c @@ -65,8 +65,8 @@ int snd_tlv_parse_dB_info(unsigned int *tlv, int err;
*db_tlvp = NULL; - type = tlv[0]; - size = tlv[1]; + type = tlv[SNDRV_CTL_TLVO_TYPE]; + size = tlv[SNDRV_CTL_TLVO_LEN]; tlv_size -= 2 * sizeof(int); if (size > tlv_size) { SNDERR("TLV size error"); @@ -83,7 +83,7 @@ int snd_tlv_parse_dB_info(unsigned int *tlv, return err; /* error */ if (err > 0) return err; /* found */ - len = int_index(tlv[1]) + 2; + len = int_index(tlv[SNDRV_CTL_TLVO_LEN]) + 2; size -= len * sizeof(int); tlv += len; } @@ -131,10 +131,10 @@ int snd_tlv_get_dB_range(unsigned int *tlv, long rangemin, long rangemax, { int err;
- switch (tlv[0]) { + switch (tlv[SNDRV_CTL_TLVO_TYPE]) { case SND_CTL_TLVT_DB_RANGE: { unsigned int pos, len; - len = int_index(tlv[1]); + len = int_index(tlv[SNDRV_CTL_TLVO_LEN]); if (len > MAX_TLV_RANGE_SIZE) return -EINVAL; pos = 2; @@ -167,22 +167,23 @@ int snd_tlv_get_dB_range(unsigned int *tlv, long rangemin, long rangemax, } case SND_CTL_TLVT_DB_SCALE: { int step; - if (tlv[3] & 0x10000) + if (tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] & 0x10000) *min = SND_CTL_TLV_DB_GAIN_MUTE; else - *min = (int)tlv[2]; - step = (tlv[3] & 0xffff); - *max = (int)tlv[2] + step * (rangemax - rangemin); + *min = (int)tlv[SNDRV_CTL_TLVO_DB_SCALE_MIN]; + step = (tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] & 0xffff); + *max = (int)tlv[SNDRV_CTL_TLVO_DB_SCALE_MIN] + + step * (rangemax - rangemin); return 0; } case SND_CTL_TLVT_DB_MINMAX: case SND_CTL_TLVT_DB_LINEAR: - *min = (int)tlv[2]; - *max = (int)tlv[3]; + *min = (int)tlv[SNDRV_CTL_TLVO_DB_LINEAR_MIN]; + *max = (int)tlv[SNDRV_CTL_TLVO_DB_LINEAR_MAX]; return 0; case SND_CTL_TLVT_DB_MINMAX_MUTE: *min = SND_CTL_TLV_DB_GAIN_MUTE; - *max = (int)tlv[3]; + *max = (int)tlv[SNDRV_CTL_TLVO_DB_MINMAX_MAX]; return 0; } return -EINVAL; @@ -200,10 +201,12 @@ int snd_tlv_get_dB_range(unsigned int *tlv, long rangemin, long rangemax, int snd_tlv_convert_to_dB(unsigned int *tlv, long rangemin, long rangemax, long volume, long *db_gain) { - switch (tlv[0]) { + unsigned int type = tlv[SNDRV_CTL_TLVO_TYPE]; + + switch (type) { case SND_CTL_TLVT_DB_RANGE: { unsigned int pos, len; - len = int_index(tlv[1]); + len = int_index(tlv[SNDRV_CTL_TLVO_LEN]); if (len > MAX_TLV_RANGE_SIZE) return -EINVAL; pos = 2; @@ -220,9 +223,9 @@ int snd_tlv_convert_to_dB(unsigned int *tlv, long rangemin, long rangemax, } case SND_CTL_TLVT_DB_SCALE: { int min, step, mute; - min = tlv[2]; - step = (tlv[3] & 0xffff); - mute = (tlv[3] >> 16) & 1; + min = tlv[SNDRV_CTL_TLVO_DB_SCALE_MIN]; + step = (tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] & 0xffff); + mute = (tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] >> 16) & 1; if (mute && volume <= rangemin) *db_gain = SND_CTL_TLV_DB_GAIN_MUTE; else @@ -232,10 +235,10 @@ int snd_tlv_convert_to_dB(unsigned int *tlv, long rangemin, long rangemax, case SND_CTL_TLVT_DB_MINMAX: case SND_CTL_TLVT_DB_MINMAX_MUTE: { int mindb, maxdb; - mindb = tlv[2]; - maxdb = tlv[3]; + mindb = tlv[SNDRV_CTL_TLVO_DB_MINMAX_MIN]; + maxdb = tlv[SNDRV_CTL_TLVO_DB_MINMAX_MAX]; if (volume <= rangemin || rangemax <= rangemin) { - if (tlv[0] == SND_CTL_TLVT_DB_MINMAX_MUTE) + if (type == SND_CTL_TLVT_DB_MINMAX_MUTE) *db_gain = SND_CTL_TLV_DB_GAIN_MUTE; else *db_gain = mindb; @@ -248,8 +251,8 @@ int snd_tlv_convert_to_dB(unsigned int *tlv, long rangemin, long rangemax, } #ifndef HAVE_SOFT_FLOAT case SND_CTL_TLVT_DB_LINEAR: { - int mindb = tlv[2]; - int maxdb = tlv[3]; + int mindb = tlv[SNDRV_CTL_TLVO_DB_LINEAR_MIN]; + int maxdb = tlv[SNDRV_CTL_TLVO_DB_LINEAR_MAX]; if (volume <= rangemin || rangemax <= rangemin) *db_gain = mindb; else if (volume >= rangemax) @@ -289,11 +292,13 @@ int snd_tlv_convert_to_dB(unsigned int *tlv, long rangemin, long rangemax, int snd_tlv_convert_from_dB(unsigned int *tlv, long rangemin, long rangemax, long db_gain, long *value, int xdir) { - switch (tlv[0]) { + unsigned int type = tlv[SNDRV_CTL_TLVO_TYPE]; + + switch (type) { case SND_CTL_TLVT_DB_RANGE: { long dbmin, dbmax, prev_submax; unsigned int pos, len; - len = int_index(tlv[1]); + len = int_index(tlv[SNDRV_CTL_TLVO_LEN]); if (len < 6 || len > MAX_TLV_RANGE_SIZE) return -EINVAL; pos = 2; @@ -324,13 +329,14 @@ int snd_tlv_convert_from_dB(unsigned int *tlv, long rangemin, long rangemax, return 0; } case SND_CTL_TLVT_DB_SCALE: { - int min, step, max; - min = tlv[2]; - step = (tlv[3] & 0xffff); + int min, step, max, mute; + min = tlv[SNDRV_CTL_TLVO_DB_SCALE_MIN]; + step = tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] & 0xffff; + mute = tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] & 0x10000; max = min + (int)(step * (rangemax - rangemin)); if (db_gain <= min) if (db_gain > SND_CTL_TLV_DB_GAIN_MUTE && xdir > 0 && - (tlv[3] & 0x10000)) + mute) *value = rangemin + 1; else *value = rangemin; @@ -348,11 +354,11 @@ int snd_tlv_convert_from_dB(unsigned int *tlv, long rangemin, long rangemax, case SND_CTL_TLVT_DB_MINMAX: case SND_CTL_TLVT_DB_MINMAX_MUTE: { int min, max; - min = tlv[2]; - max = tlv[3]; + min = tlv[SNDRV_CTL_TLVO_DB_MINMAX_MIN]; + max = tlv[SNDRV_CTL_TLVO_DB_MINMAX_MAX]; if (db_gain <= min) if (db_gain > SND_CTL_TLV_DB_GAIN_MUTE && xdir > 0 && - tlv[0] == SND_CTL_TLVT_DB_MINMAX_MUTE) + type == SND_CTL_TLVT_DB_MINMAX_MUTE) *value = rangemin + 1; else *value = rangemin; @@ -370,8 +376,8 @@ int snd_tlv_convert_from_dB(unsigned int *tlv, long rangemin, long rangemax, #ifndef HAVE_SOFT_FLOAT case SND_CTL_TLVT_DB_LINEAR: { int min, max; - min = tlv[2]; - max = tlv[3]; + min = tlv[SNDRV_CTL_TLVO_DB_LINEAR_MIN]; + max = tlv[SNDRV_CTL_TLVO_DB_LINEAR_MAX]; if (db_gain <= min) *value = rangemin; else if (db_gain >= max)
A series of SNDRV_CTL_TLVO_XXX macro was introduced for position offset of TLV data. This commit applies a code optimization.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- src/control/hcontrol.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/control/hcontrol.c b/src/control/hcontrol.c index 7e775248..0cac8956 100644 --- a/src/control/hcontrol.c +++ b/src/control/hcontrol.c @@ -870,7 +870,7 @@ int snd_hctl_elem_tlv_write(snd_hctl_elem_t *elem, const unsigned int *tlv) { assert(elem); assert(tlv); - assert(tlv[1] >= 4); + assert(tlv[SNDRV_CTL_TLVO_LEN] >= 4); return snd_ctl_elem_tlv_write(elem->hctl->ctl, &elem->id, tlv); }
@@ -886,7 +886,7 @@ int snd_hctl_elem_tlv_command(snd_hctl_elem_t *elem, const unsigned int *tlv) { assert(elem); assert(tlv); - assert(tlv[1] >= 4); + assert(tlv[SNDRV_CTL_TLVO_LEN] >= 4); return snd_ctl_elem_tlv_command(elem->hctl->ctl, &elem->id, tlv); }
A series of SNDRV_CTL_TLVO_XXX macro was introduced for position offset of TLV data. This commit applies a code optimization.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- src/pcm/pcm_hw.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c index 65b198c5..a728b23b 100644 --- a/src/pcm/pcm_hw.c +++ b/src/pcm/pcm_hw.c @@ -1199,6 +1199,7 @@ snd_pcm_query_chmaps_from_hw(int card, int dev, int subdev, snd_ctl_t *ctl; snd_ctl_elem_id_t id = {0}; unsigned int tlv[2048], *start; + unsigned int type; snd_pcm_chmap_query_t **map; int i, ret, nums;
@@ -1223,9 +1224,10 @@ snd_pcm_query_chmaps_from_hw(int card, int dev, int subdev, /* FIXME: the parser below assumes that the TLV only contains * chmap-related blocks */ - if (tlv[0] != SND_CTL_TLVT_CONTAINER) { - if (!is_chmap_type(tlv[0])) { - SYSMSG("Invalid TLV type %d\n", tlv[0]); + type = tlv[SNDRV_CTL_TLVO_TYPE]; + if (type != SND_CTL_TLVT_CONTAINER) { + if (!is_chmap_type(type)) { + SYSMSG("Invalid TLV type %d\n", type); return NULL; } start = tlv; @@ -1234,7 +1236,7 @@ snd_pcm_query_chmaps_from_hw(int card, int dev, int subdev, unsigned int *p; int size; start = tlv + 2; - size = tlv[1]; + size = tlv[SNDRV_CTL_TLVO_LEN]; nums = 0; for (p = start; size > 0; ) { if (!is_chmap_type(p[0])) {
A series of SNDRV_CTL_TLVO_XXX macro was introduced for position offset of TLV data. This commit applies a code optimization.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- src/pcm/pcm_softvol.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/src/pcm/pcm_softvol.c b/src/pcm/pcm_softvol.c index 0eaeacef..f08208f8 100644 --- a/src/pcm/pcm_softvol.c +++ b/src/pcm/pcm_softvol.c @@ -31,6 +31,8 @@ #include "pcm_local.h" #include "pcm_plugin.h"
+#include <sound/tlv.h> + #ifndef PIC /* entry for static linking */ const char *_snd_module_pcm_softvol = ""; @@ -708,10 +710,11 @@ static void snd_pcm_softvol_dump(snd_pcm_t *pcm, snd_output_t *out) static int add_tlv_info(snd_pcm_softvol_t *svol, snd_ctl_elem_info_t *cinfo) { unsigned int tlv[4]; - tlv[0] = SND_CTL_TLVT_DB_SCALE; - tlv[1] = 2 * sizeof(int); - tlv[2] = (int)(svol->min_dB * 100); - tlv[3] = (int)((svol->max_dB - svol->min_dB) * 100 / svol->max_val); + tlv[SNDRV_CTL_TLVO_TYPE] = SND_CTL_TLVT_DB_SCALE; + tlv[SNDRV_CTL_TLVO_LEN] = 2 * sizeof(int); + tlv[SNDRV_CTL_TLVO_DB_SCALE_MIN] = (int)(svol->min_dB * 100); + tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] = + (int)((svol->max_dB - svol->min_dB) * 100 / svol->max_val); return snd_ctl_elem_tlv_write(svol->ctl, &cinfo->id, tlv); }
A series of SNDRV_CTL_TLVO_XXX macro was introduced for position offset of TLV data. This commit applies a code optimization.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- test/user-ctl-element-set.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test/user-ctl-element-set.c b/test/user-ctl-element-set.c index e94152b9..fee130e2 100644 --- a/test/user-ctl-element-set.c +++ b/test/user-ctl-element-set.c @@ -660,7 +660,7 @@ static int check_tlv(struct elem_set_trial *trial) if (err < 0) return err;
- len = tlv[1] + sizeof(unsigned int) * 2; + len = tlv[SNDRV_CTL_TLVO_LEN] + sizeof(unsigned int) * 2; curr = malloc(len); if (curr == NULL) { free(tlv);
On Tue, 15 May 2018 14:36:33 +0200, Takashi Sakamoto wrote:
Hi,
In development period for Linux v4.18, a series of SNDRV_CTL_TLVO_XXX macro was introduced to kernel stuffs for position offset of TLV data.
This patchset backports the macros to this library as well as adds code optimization with them.
Takashi Sakamoto (6): control: add a series of macro for offset of several types of TLV control: use position offset macro of TLV data hcontrol: use position offset macro of TLV data pcm: hw: use position offset macro of TLV data pcm: softvol: use position offset macro of TLV data test: use position offset macro of TLV data
Applied all patches. Thanks.
Takashi
participants (2)
-
Takashi Iwai
-
Takashi Sakamoto