diff --git a/.alsa-lib.metadata b/.alsa-lib.metadata new file mode 100644 index 0000000..3dd896f --- /dev/null +++ b/.alsa-lib.metadata @@ -0,0 +1 @@ +628634afbdc19054fca26d714aa6c2f1e41e465d SOURCES/alsa-lib-1.1.4.1.tar.bz2 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f2718d2 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/alsa-lib-1.1.4.1.tar.bz2 diff --git a/README.md b/README.md deleted file mode 100644 index 0e7897f..0000000 --- a/README.md +++ /dev/null @@ -1,5 +0,0 @@ -The master branch has no content - -Look at the c7 branch if you are working with CentOS-7, or the c4/c5/c6 branch for CentOS-4, 5 or 6 - -If you find this file in a distro specific branch, it means that no content has been checked in yet diff --git a/SOURCES/alsa-lib-1.1.0-config.patch b/SOURCES/alsa-lib-1.1.0-config.patch new file mode 100644 index 0000000..76aaa8e --- /dev/null +++ b/SOURCES/alsa-lib-1.1.0-config.patch @@ -0,0 +1,40 @@ +--- alsa-lib-1.1.0/src/conf/alsa.conf.config 2016-01-12 13:07:56.904218949 +0100 ++++ alsa-lib-1.1.0/src/conf/alsa.conf 2016-01-12 13:09:16.164164628 +0100 +@@ -73,8 +73,7 @@ + defaults.pcm.compat 0 + defaults.pcm.minperiodtime 5000 # in us + defaults.pcm.ipc_key 5678293 +-defaults.pcm.ipc_gid audio +-defaults.pcm.ipc_perm 0660 ++defaults.pcm.ipc_perm 0600 + defaults.pcm.dmix.max_periods 0 + defaults.pcm.dmix.rate 48000 + defaults.pcm.dmix.format "unchanged" +diff -ruNp alsa-lib-1.0.17.orig/src/conf/pcm/dmix.conf alsa-lib-1.0.17/src/conf/pcm/dmix.conf +--- alsa-lib-1.0.17.orig/src/conf/pcm/dmix.conf 2008-07-14 10:57:56.000000000 +0200 ++++ alsa-lib-1.0.17/src/conf/pcm/dmix.conf 2008-07-21 11:51:45.000000000 +0200 +@@ -41,10 +41,6 @@ pcm.!dmix { + @func refer + name defaults.pcm.ipc_key + } +- ipc_gid { +- @func refer +- name defaults.pcm.ipc_gid +- } + ipc_perm { + @func refer + name defaults.pcm.ipc_perm +diff -ruNp alsa-lib-1.0.17.orig/src/conf/pcm/dsnoop.conf alsa-lib-1.0.17/src/conf/pcm/dsnoop.conf +--- alsa-lib-1.0.17.orig/src/conf/pcm/dsnoop.conf 2008-07-14 10:57:56.000000000 +0200 ++++ alsa-lib-1.0.17/src/conf/pcm/dsnoop.conf 2008-07-21 11:51:45.000000000 +0200 +@@ -41,10 +41,6 @@ pcm.!dsnoop { + @func refer + name defaults.pcm.ipc_key + } +- ipc_gid { +- @func refer +- name defaults.pcm.ipc_gid +- } + ipc_perm { + @func refer + name defaults.pcm.ipc_perm diff --git a/SOURCES/alsa-lib-1.1.4.1-post.patch b/SOURCES/alsa-lib-1.1.4.1-post.patch new file mode 100644 index 0000000..3d26a42 --- /dev/null +++ b/SOURCES/alsa-lib-1.1.4.1-post.patch @@ -0,0 +1,4493 @@ +From 6d843ba5d377961f6765466ba0cc362dd10f7557 Mon Sep 17 00:00:00 2001 +From: Liam Girdwood +Date: Wed, 14 Jun 2017 12:37:39 +0100 +Subject: [PATCH 01/39] topology: Add support for missing fields parser. + +The alsa-lib topology parser is missing some fields for certain objects that +are part of the ABI. This patch adds the missing fields to the parser. + +Signed-off-by: Liam Girdwood +Signed-off-by: Takashi Iwai +--- + src/topology/pcm.c | 183 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 183 insertions(+) + +diff --git a/src/topology/pcm.c b/src/topology/pcm.c +index daef20e4..0f4deb4f 100644 +--- a/src/topology/pcm.c ++++ b/src/topology/pcm.c +@@ -383,6 +383,49 @@ int tplg_parse_stream_caps(snd_tplg_t *tplg, + tplg_dbg("\t\t%s: %d\n", id, sc->channels_max); + continue; + } ++ ++ if (strcmp(id, "periods_min") == 0) { ++ sc->periods_min = atoi(val); ++ tplg_dbg("\t\t%s: %d\n", id, sc->periods_min); ++ continue; ++ } ++ ++ if (strcmp(id, "periods_max") == 0) { ++ sc->periods_max = atoi(val); ++ tplg_dbg("\t\t%s: %d\n", id, sc->periods_max); ++ continue; ++ } ++ ++ if (strcmp(id, "period_size_min") == 0) { ++ sc->period_size_min = atoi(val); ++ tplg_dbg("\t\t%s: %d\n", id, sc->period_size_min); ++ continue; ++ } ++ ++ if (strcmp(id, "period_size_max") == 0) { ++ sc->period_size_max = atoi(val); ++ tplg_dbg("\t\t%s: %d\n", id, sc->period_size_max); ++ continue; ++ } ++ ++ if (strcmp(id, "buffer_size_min") == 0) { ++ sc->buffer_size_min = atoi(val); ++ tplg_dbg("\t\t%s: %d\n", id, sc->buffer_size_min); ++ continue; ++ } ++ ++ if (strcmp(id, "buffer_size_max") == 0) { ++ sc->buffer_size_max = atoi(val); ++ tplg_dbg("\t\t%s: %d\n", id, sc->buffer_size_max); ++ continue; ++ } ++ ++ if (strcmp(id, "sig_bits") == 0) { ++ sc->sig_bits = atoi(val); ++ tplg_dbg("\t\t%s: %d\n", id, sc->sig_bits); ++ continue; ++ } ++ + } + + return 0; +@@ -572,6 +615,17 @@ int tplg_parse_pcm(snd_tplg_t *tplg, + continue; + } + ++ if (strcmp(id, "compress") == 0) { ++ if (snd_config_get_string(n, &val) < 0) ++ return -EINVAL; ++ ++ if (strcmp(val, "true") == 0) ++ pcm->compress = 1; ++ ++ tplg_dbg("\t%s: %s\n", id, val); ++ continue; ++ } ++ + if (strcmp(id, "dai") == 0) { + err = tplg_parse_compound(tplg, n, + tplg_parse_fe_dai, elem); +@@ -655,6 +709,26 @@ int tplg_parse_dai(snd_tplg_t *tplg, + continue; + } + ++ if (strcmp(id, "playback") == 0) { ++ if (snd_config_get_string(n, &val) < 0) ++ return -EINVAL; ++ ++ dai->playback = atoi(val); ++ tplg_dbg("\t%s: %d\n", id, dai->playback); ++ continue; ++ } ++ ++ ++ if (strcmp(id, "capture") == 0) { ++ if (snd_config_get_string(n, &val) < 0) ++ return -EINVAL; ++ ++ dai->capture = atoi(val); ++ tplg_dbg("\t%s: %d\n", id, dai->capture); ++ continue; ++ } ++ ++ + /* stream capabilities */ + if (strcmp(id, "pcm") == 0) { + err = tplg_parse_compound(tplg, n, +@@ -997,6 +1071,23 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg, + continue; + } + ++ if (strcmp(id, "bclk_freq") == 0) { ++ if (snd_config_get_string(n, &val) < 0) ++ return -EINVAL; ++ ++ hw_cfg->bclk_rate = atoi(val); ++ continue; ++ } ++ ++ if (strcmp(id, "bclk_invert") == 0) { ++ if (snd_config_get_string(n, &val) < 0) ++ return -EINVAL; ++ ++ if (!strcmp(val, "true")) ++ hw_cfg->invert_bclk = true; ++ continue; ++ } ++ + if (strcmp(id, "fsync") == 0) { + if (snd_config_get_string(n, &val) < 0) + return -EINVAL; +@@ -1005,6 +1096,98 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg, + hw_cfg->fsync_master = true; + continue; + } ++ ++ if (strcmp(id, "fsync_invert") == 0) { ++ if (snd_config_get_string(n, &val) < 0) ++ return -EINVAL; ++ ++ if (!strcmp(val, "true")) ++ hw_cfg->invert_fsync = true; ++ continue; ++ } ++ ++ if (strcmp(id, "fsync_freq") == 0) { ++ if (snd_config_get_string(n, &val) < 0) ++ return -EINVAL; ++ ++ hw_cfg->fsync_rate = atoi(val); ++ continue; ++ } ++ ++ if (strcmp(id, "mclk_freq") == 0) { ++ if (snd_config_get_string(n, &val) < 0) ++ return -EINVAL; ++ ++ hw_cfg->mclk_rate = atoi(val); ++ continue; ++ } ++ ++ if (strcmp(id, "mclk") == 0) { ++ if (snd_config_get_string(n, &val) < 0) ++ return -EINVAL; ++ ++ if (!strcmp(val, "master")) ++ hw_cfg->mclk_direction = true; ++ continue; ++ } ++ ++ if (strcmp(id, "pm_gate_clocks") == 0) { ++ if (snd_config_get_string(n, &val) < 0) ++ return -EINVAL; ++ ++ if (!strcmp(val, "true")) ++ hw_cfg->clock_gated = true; ++ continue; ++ } ++ ++ if (strcmp(id, "tdm_slots") == 0) { ++ if (snd_config_get_string(n, &val) < 0) ++ return -EINVAL; ++ ++ hw_cfg->tdm_slots = atoi(val); ++ continue; ++ } ++ ++ if (strcmp(id, "tdm_slot_width") == 0) { ++ if (snd_config_get_string(n, &val) < 0) ++ return -EINVAL; ++ ++ hw_cfg->tdm_slot_width = atoi(val); ++ continue; ++ } ++ ++ if (strcmp(id, "tx_slots") == 0) { ++ if (snd_config_get_string(n, &val) < 0) ++ return -EINVAL; ++ ++ hw_cfg->tx_slots = atoi(val); ++ continue; ++ } ++ ++ if (strcmp(id, "rx_slots") == 0) { ++ if (snd_config_get_string(n, &val) < 0) ++ return -EINVAL; ++ ++ hw_cfg->rx_slots = atoi(val); ++ continue; ++ } ++ ++ if (strcmp(id, "tx_channels") == 0) { ++ if (snd_config_get_string(n, &val) < 0) ++ return -EINVAL; ++ ++ hw_cfg->tx_channels = atoi(val); ++ continue; ++ } ++ ++ if (strcmp(id, "rx_channels") == 0) { ++ if (snd_config_get_string(n, &val) < 0) ++ return -EINVAL; ++ ++ hw_cfg->rx_channels = atoi(val); ++ continue; ++ } ++ + } + + return 0; +-- +2.13.5 + + +From 89c96ad7fb0168411260196560892835d0adeddf Mon Sep 17 00:00:00 2001 +From: Liam Girdwood +Date: Wed, 14 Jun 2017 12:37:40 +0100 +Subject: [PATCH 02/39] topology: disable alsa-lib topology debug output by + default. + +Signed-off-by: Liam Girdwood +Signed-off-by: Takashi Iwai +--- + src/topology/tplg_local.h | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h +index 42e3201d..60af0177 100644 +--- a/src/topology/tplg_local.h ++++ b/src/topology/tplg_local.h +@@ -22,7 +22,6 @@ + #include + #include + +-#define TPLG_DEBUG + #ifdef TPLG_DEBUG + #define tplg_dbg SNDERR + #else +-- +2.13.5 + + +From c550a421a3ff5b11ccd4a506ae04fdc6c5347ae3 Mon Sep 17 00:00:00 2001 +From: Guneshwor Singh +Date: Tue, 20 Jun 2017 09:45:45 +0530 +Subject: [PATCH 03/39] topology: Add parsing for rates from conf + +In alsa-lib topology parser, rate_min and rate_max are parsed currently. +Add support to parse rates also. + +Signed-off-by: Guneshwor Singh +Signed-off-by: Takashi Iwai +--- + include/topology.h | 1 + + src/topology/pcm.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++ + src/topology/tplg_local.h | 20 +++++++++++++ + 3 files changed, 92 insertions(+) + +diff --git a/include/topology.h b/include/topology.h +index ccb3a004..42d23762 100644 +--- a/include/topology.h ++++ b/include/topology.h +@@ -534,6 +534,7 @@ extern "C" { + * SectionPCMCapabilities."name" { + * + * formats "S24_LE,S16_LE" # Supported formats ++ * rates "48000" # Supported rates + * rate_min "48000" # Max supported sample rate + * rate_max "48000" # Min supported sample rate + * channels_min "2" # Min number of channels +diff --git a/src/topology/pcm.c b/src/topology/pcm.c +index 0f4deb4f..bb63142e 100644 +--- a/src/topology/pcm.c ++++ b/src/topology/pcm.c +@@ -20,6 +20,26 @@ + #include "list.h" + #include "tplg_local.h" + ++#define RATE(v) [SND_PCM_RATE_##v] = #v ++ ++static const char *const snd_pcm_rate_names[] = { ++ RATE(5512), ++ RATE(8000), ++ RATE(11025), ++ RATE(16000), ++ RATE(22050), ++ RATE(32000), ++ RATE(44100), ++ RATE(48000), ++ RATE(64000), ++ RATE(88200), ++ RATE(96000), ++ RATE(176400), ++ RATE(192000), ++ RATE(CONTINUOUS), ++ RATE(KNOT), ++}; ++ + struct tplg_elem *lookup_pcm_dai_stream(struct list_head *base, const char* id) + { + struct list_head *pos; +@@ -309,6 +329,42 @@ static int split_format(struct snd_soc_tplg_stream_caps *caps, char *str) + return 0; + } + ++static int get_rate_value(const char* name) ++{ ++ int rate; ++ for (rate = 0; rate <= SND_PCM_RATE_LAST; rate++) { ++ if (snd_pcm_rate_names[rate] && ++ strcasecmp(name, snd_pcm_rate_names[rate]) == 0) { ++ return rate; ++ } ++ } ++ ++ return SND_PCM_RATE_UNKNOWN; ++} ++ ++static int split_rate(struct snd_soc_tplg_stream_caps *caps, char *str) ++{ ++ char *s = NULL; ++ snd_pcm_rates_t rate; ++ int i = 0; ++ ++ s = strtok(str, ","); ++ while (s) { ++ rate = get_rate_value(s); ++ ++ if (rate == SND_PCM_RATE_UNKNOWN) { ++ SNDERR("error: unsupported stream rate %s\n", s); ++ return -EINVAL; ++ } ++ ++ caps->rates |= 1 << rate; ++ s = strtok(NULL, ", "); ++ i++; ++ } ++ ++ return 0; ++} ++ + /* Parse pcm stream capabilities */ + int tplg_parse_stream_caps(snd_tplg_t *tplg, + snd_config_t *cfg, void *private ATTRIBUTE_UNUSED) +@@ -360,6 +416,21 @@ int tplg_parse_stream_caps(snd_tplg_t *tplg, + continue; + } + ++ if (strcmp(id, "rates") == 0) { ++ s = strdup(val); ++ if (!s) ++ return -ENOMEM; ++ ++ err = split_rate(sc, s); ++ free(s); ++ ++ if (err < 0) ++ return err; ++ ++ tplg_dbg("\t\t%s: %s\n", id, val); ++ continue; ++ } ++ + if (strcmp(id, "rate_min") == 0) { + sc->rate_min = atoi(val); + tplg_dbg("\t\t%s: %d\n", id, sc->rate_min); +diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h +index 60af0177..af599145 100644 +--- a/src/topology/tplg_local.h ++++ b/src/topology/tplg_local.h +@@ -37,6 +37,26 @@ + struct tplg_ref; + struct tplg_elem; + ++typedef enum _snd_pcm_rates { ++ SND_PCM_RATE_UNKNOWN = -1, ++ SND_PCM_RATE_5512 = 0, ++ SND_PCM_RATE_8000, ++ SND_PCM_RATE_11025, ++ SND_PCM_RATE_16000, ++ SND_PCM_RATE_22050, ++ SND_PCM_RATE_32000, ++ SND_PCM_RATE_44100, ++ SND_PCM_RATE_48000, ++ SND_PCM_RATE_64000, ++ SND_PCM_RATE_88200, ++ SND_PCM_RATE_96000, ++ SND_PCM_RATE_176400, ++ SND_PCM_RATE_192000, ++ SND_PCM_RATE_CONTINUOUS = 30, ++ SND_PCM_RATE_KNOT = 31, ++ SND_PCM_RATE_LAST = SND_PCM_RATE_KNOT, ++} snd_pcm_rates_t; ++ + struct snd_tplg { + + /* opaque vendor data */ +-- +2.13.5 + + +From 6c535573008e474c471c100c5bfa5383308020f3 Mon Sep 17 00:00:00 2001 +From: Alexander Tsoy +Date: Sun, 18 Jun 2017 23:23:02 +0300 +Subject: [PATCH 04/39] conf: USB-Audio: fix dsnoop args for Audiophile USB + card + +Fixes: a9b129955659 ("USB-Audio.conf: fix definition for M-Audio AudioP...") +Signed-off-by: Alexander Tsoy +Signed-off-by: Takashi Iwai +--- + src/conf/cards/USB-Audio.conf | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/conf/cards/USB-Audio.conf b/src/conf/cards/USB-Audio.conf +index e365f297..f72ef121 100644 +--- a/src/conf/cards/USB-Audio.conf ++++ b/src/conf/cards/USB-Audio.conf +@@ -90,7 +90,7 @@ USB-Audio."Audiophile USB (tm)".pcm.default { + type plug + slave.pcm { + @func concat +- strings [ "dsnoop:DEVICE=1,CARD=" $CARD ] ++ strings [ "dsnoop:DEV=1,CARD=" $CARD ] + } + } + } +-- +2.13.5 + + +From c09e3b2d5b7fe893b99df3c87577936a3f386d99 Mon Sep 17 00:00:00 2001 +From: Alexander Tsoy +Date: Sun, 18 Jun 2017 23:23:03 +0300 +Subject: [PATCH 05/39] conf: USB-Audio: allow custom definitions for "default" + devices + +Fixes: a9b129955659 ("USB-Audio.conf: fix definition for M-Audio AudioP...") +Signed-off-by: Alexander Tsoy +Signed-off-by: Takashi Iwai +--- + src/conf/cards/USB-Audio.conf | 77 ++++++++++++++++++++++++------------------- + 1 file changed, 44 insertions(+), 33 deletions(-) + +diff --git a/src/conf/cards/USB-Audio.conf b/src/conf/cards/USB-Audio.conf +index f72ef121..cc8c718c 100644 +--- a/src/conf/cards/USB-Audio.conf ++++ b/src/conf/cards/USB-Audio.conf +@@ -67,7 +67,7 @@ USB-Audio.pcm.iec958_2_device { + } + + +-# If a device requires non-standard definitions for front, surround40, ++# If a device requires non-standard definitions for front, default, surround40, + # surround51, surround71 or iec958, they can be defined here. + + # M-Audio AudioPhile USB: +@@ -125,13 +125,13 @@ USB-Audio."Audio Advantage MicroII".pcm.iec958 { + @args.AES2 { type integer } + @args.AES3 { type integer } + +- type hooks +- slave.pcm { ++ type hooks ++ slave.pcm { + type hw + card $CARD +- } ++ } + +- hooks.0 { ++ hooks.0 { + type ctl_elems + hook_args [ + { +@@ -174,41 +174,52 @@ USB-Audio.pcm.front.0 { + card $CARD + device 0 + } +-} ++} + + USB-Audio.pcm.default { + @args [ CARD ] + @args.CARD { type string } +- type asym +- playback.pcm { +- type plug +- slave.pcm { +- @func refer +- name { +- @func concat +- strings [ +- "cards.USB-Audio.pcm.default_playback_dmix_" +- { +- @func refer +- name { +- @func concat +- strings [ +- "cards.USB-Audio.pcm.use_dmix." +- { @func card_name card $CARD } +- ] ++ @func refer ++ name { ++ @func concat ++ strings [ ++ "cards.USB-Audio." ++ { @func card_name card $CARD } ++ ".pcm.default:CARD=" $CARD ++ ] ++ } ++ default { ++ type asym ++ playback.pcm { ++ type plug ++ slave.pcm { ++ @func refer ++ name { ++ @func concat ++ strings [ ++ "cards.USB-Audio.pcm.default_playback_dmix_" ++ { ++ @func refer ++ name { ++ @func concat ++ strings [ ++ "cards.USB-Audio.pcm.use_dmix." ++ { @func card_name card $CARD } ++ ] ++ } ++ default yes + } +- default yes +- } +- ":CARD=" $CARD +- ] ++ ":CARD=" $CARD ++ ] ++ } + } + } +- } +- capture.pcm { +- type plug +- slave.pcm { +- @func concat +- strings [ "dsnoop:" $CARD ] ++ capture.pcm { ++ type plug ++ slave.pcm { ++ @func concat ++ strings [ "dsnoop:" $CARD ] ++ } + } + } + } +-- +2.13.5 + + +From f10bc243e42142c568d90f540e806aefb45d8bac Mon Sep 17 00:00:00 2001 +From: Takashi Sakamoto +Date: Fri, 23 Jun 2017 22:09:23 +0900 +Subject: [PATCH 06/39] pcm: obsolete 'mmap_emulation' parameter of + snd_pcm_hw_open_fd() + +A function, snd_pcm_hw_open_fd(), is just for internal use. This function +has an obsoleted parameter and we can remove it without any compatibility +issue. + +Signed-off-by: Takashi Sakamoto +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_direct.c | 2 +- + src/pcm/pcm_hw.c | 6 ++---- + src/pcm/pcm_local.h | 3 ++- + 3 files changed, 5 insertions(+), 6 deletions(-) + +diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c +index 43702601..9fd376d8 100644 +--- a/src/pcm/pcm_direct.c ++++ b/src/pcm/pcm_direct.c +@@ -1523,7 +1523,7 @@ int snd_pcm_direct_open_secondary_client(snd_pcm_t **spcmp, snd_pcm_direct_t *dm + int ret; + snd_pcm_t *spcm; + +- ret = snd_pcm_hw_open_fd(spcmp, client_name, dmix->hw_fd, 0, 0); ++ ret = snd_pcm_hw_open_fd(spcmp, client_name, dmix->hw_fd, 0); + if (ret < 0) { + SNDERR("unable to open hardware"); + return ret; +diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c +index 30cd5d0f..f0efcde3 100644 +--- a/src/pcm/pcm_hw.c ++++ b/src/pcm/pcm_hw.c +@@ -1410,15 +1410,13 @@ static const snd_pcm_fast_ops_t snd_pcm_hw_fast_ops_timer = { + * \param pcmp Returns created PCM handle + * \param name Name of PCM + * \param fd File descriptor +- * \param mmap_emulation Obsoleted parameter + * \param sync_ptr_ioctl Boolean flag for sync_ptr ioctl + * \retval zero on success otherwise a negative error code + * \warning Using of this function might be dangerous in the sense + * of compatibility reasons. The prototype might be freely + * changed in future. + */ +-int snd_pcm_hw_open_fd(snd_pcm_t **pcmp, const char *name, +- int fd, int mmap_emulation ATTRIBUTE_UNUSED, ++int snd_pcm_hw_open_fd(snd_pcm_t **pcmp, const char *name, int fd, + int sync_ptr_ioctl) + { + int ver, mode; +@@ -1615,7 +1613,7 @@ int snd_pcm_hw_open(snd_pcm_t **pcmp, const char *name, + } + } + snd_ctl_close(ctl); +- return snd_pcm_hw_open_fd(pcmp, name, fd, 0, sync_ptr_ioctl); ++ return snd_pcm_hw_open_fd(pcmp, name, fd, sync_ptr_ioctl); + _err: + snd_ctl_close(ctl); + return ret; +diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h +index e4f65218..7600daa3 100644 +--- a/src/pcm/pcm_local.h ++++ b/src/pcm/pcm_local.h +@@ -935,7 +935,8 @@ snd_pcm_open_slave(snd_pcm_t **pcmp, snd_config_t *root, + + #define snd_pcm_conf_generic_id(id) _snd_conf_generic_id(id) + +-int snd_pcm_hw_open_fd(snd_pcm_t **pcmp, const char *name, int fd, int mmap_emulation, int sync_ptr_ioctl); ++int snd_pcm_hw_open_fd(snd_pcm_t **pcmp, const char *name, int fd, ++ int sync_ptr_ioctl); + int __snd_pcm_mmap_emul_open(snd_pcm_t **pcmp, const char *name, + snd_pcm_t *slave, int close_slave); + +-- +2.13.5 + + +From 8beab3eb8a4346f823cb42c507122f0abbf9025f Mon Sep 17 00:00:00 2001 +From: Takashi Sakamoto +Date: Fri, 23 Jun 2017 22:09:24 +0900 +Subject: [PATCH 07/39] pcm: minor code cleanup for ioctl call + +When error occurs, return value from ioctl(2) is -1 and error code can +be got thread local variable, errno. It's OK just to check the return +value without any assignment. + +Signed-off-by: Takashi Sakamoto +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_hw.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c +index f0efcde3..de6fd1af 100644 +--- a/src/pcm/pcm_hw.c ++++ b/src/pcm/pcm_hw.c +@@ -132,8 +132,7 @@ static int sync_ptr1(snd_pcm_hw_t *hw, unsigned int flags) + { + int err; + hw->sync_ptr->flags = flags; +- err = ioctl((hw)->fd, SNDRV_PCM_IOCTL_SYNC_PTR, (hw)->sync_ptr); +- if (err < 0) { ++ if (ioctl(hw->fd, SNDRV_PCM_IOCTL_SYNC_PTR, hw->sync_ptr) < 0) { + err = -errno; + SYSMSG("SNDRV_PCM_IOCTL_SYNC_PTR failed (%i)", err); + return err; +-- +2.13.5 + + +From 987788dbfe65ae7811868654ba11c05b4582955f Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Tue, 20 Jun 2017 12:39:23 +0200 +Subject: [PATCH 08/39] pcm: hw: Remove superfluous call of + snd_pcm_set_appl_ptr() + +There is a call of snd_pcm_set_appl_ptr() in snd_pcm_hw_hw_params() +only for the capture direction. This must be a leftover from the +ancient code. Although it's harmless for now, it's superfluous and +confusing. Let's kill it. + +Reviewed-by: Takashi Sakamoto +Tested-by: Takashi Sakamoto +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_hw.c | 9 +-------- + 1 file changed, 1 insertion(+), 8 deletions(-) + +diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c +index de6fd1af..a648d12c 100644 +--- a/src/pcm/pcm_hw.c ++++ b/src/pcm/pcm_hw.c +@@ -329,14 +329,7 @@ static int snd_pcm_hw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) + params->info &= ~0xf0000000; + if (pcm->tstamp_type != SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY) + params->info |= SND_PCM_INFO_MONOTONIC; +- err = sync_ptr(hw, 0); +- if (err < 0) +- return err; +- if (pcm->stream == SND_PCM_STREAM_CAPTURE) { +- snd_pcm_set_appl_ptr(pcm, &hw->mmap_control->appl_ptr, hw->fd, +- SNDRV_PCM_MMAP_OFFSET_CONTROL); +- } +- return 0; ++ return sync_ptr(hw, 0); + } + + static void snd_pcm_hw_close_timer(snd_pcm_hw_t *hw) +-- +2.13.5 + + +From 2fbad9bc4ead7ea0c19529c4496080af9b8ab275 Mon Sep 17 00:00:00 2001 +From: Takashi Sakamoto +Date: Sun, 25 Jun 2017 13:41:19 +0900 +Subject: [PATCH 09/39] pcm: hw: add helper functions to map/unmap + status/control data for runtime of PCM substream + +Handling mapping operation for status/control data includes some +supplemental operations for fallback mode. It's better to have helper +functions for this purpose. + +This commit adds the helper functions. + +Signed-off-by: Takashi Sakamoto +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_hw.c | 48 ++++++++++++++++++++++++++++++++++-------------- + 1 file changed, 34 insertions(+), 14 deletions(-) + +diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c +index a648d12c..abf4afe0 100644 +--- a/src/pcm/pcm_hw.c ++++ b/src/pcm/pcm_hw.c +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -866,7 +867,7 @@ static snd_pcm_sframes_t snd_pcm_hw_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_u + return xfern.result; + } + +-static int snd_pcm_hw_mmap_status(snd_pcm_t *pcm) ++static int map_status_data(snd_pcm_t *pcm) + { + snd_pcm_hw_t *hw = pcm->private_data; + struct snd_pcm_sync_ptr sync_ptr; +@@ -900,7 +901,7 @@ static int snd_pcm_hw_mmap_status(snd_pcm_t *pcm) + return 0; + } + +-static int snd_pcm_hw_mmap_control(snd_pcm_t *pcm) ++static int map_control_data(snd_pcm_t *pcm) + { + snd_pcm_hw_t *hw = pcm->private_data; + void *ptr; +@@ -922,10 +923,28 @@ static int snd_pcm_hw_mmap_control(snd_pcm_t *pcm) + return 0; + } + +-static int snd_pcm_hw_munmap_status(snd_pcm_t *pcm) ++static int map_status_and_control_data(snd_pcm_t *pcm, bool force_fallback) + { + snd_pcm_hw_t *hw = pcm->private_data; + int err; ++ ++ hw->sync_ptr_ioctl = (int)force_fallback; ++ ++ err = map_status_data(pcm); ++ if (err < 0) ++ return err; ++ ++ err = map_control_data(pcm); ++ if (err < 0) ++ return err; ++ ++ return 0; ++} ++ ++static int unmap_status_data(snd_pcm_hw_t *hw) ++{ ++ int err; ++ + if (hw->sync_ptr_ioctl) { + free(hw->sync_ptr); + hw->sync_ptr = NULL; +@@ -939,10 +958,10 @@ static int snd_pcm_hw_munmap_status(snd_pcm_t *pcm) + return 0; + } + +-static int snd_pcm_hw_munmap_control(snd_pcm_t *pcm) ++static int unmap_control_data(snd_pcm_hw_t *hw) + { +- snd_pcm_hw_t *hw = pcm->private_data; + int err; ++ + if (hw->sync_ptr_ioctl) { + free(hw->sync_ptr); + hw->sync_ptr = NULL; +@@ -956,6 +975,12 @@ static int snd_pcm_hw_munmap_control(snd_pcm_t *pcm) + return 0; + } + ++static void unmap_status_and_control_data(snd_pcm_hw_t *hw) ++{ ++ unmap_status_data(hw); ++ unmap_control_data(hw); ++} ++ + static int snd_pcm_hw_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) + { + return 0; +@@ -974,8 +999,9 @@ static int snd_pcm_hw_close(snd_pcm_t *pcm) + err = -errno; + SYSMSG("close failed (%i)\n", err); + } +- snd_pcm_hw_munmap_status(pcm); +- snd_pcm_hw_munmap_control(pcm); ++ ++ unmap_status_and_control_data(hw); ++ + free(hw); + return err; + } +@@ -1484,7 +1510,6 @@ int snd_pcm_hw_open_fd(snd_pcm_t **pcmp, const char *name, int fd, + hw->device = info.device; + hw->subdevice = info.subdevice; + hw->fd = fd; +- hw->sync_ptr_ioctl = sync_ptr_ioctl; + /* no restriction */ + hw->format = SND_PCM_FORMAT_UNKNOWN; + hw->rate = 0; +@@ -1508,12 +1533,7 @@ int snd_pcm_hw_open_fd(snd_pcm_t **pcmp, const char *name, int fd, + #endif + pcm->own_state_check = 1; /* skip the common state check */ + +- ret = snd_pcm_hw_mmap_status(pcm); +- if (ret < 0) { +- snd_pcm_close(pcm); +- return ret; +- } +- ret = snd_pcm_hw_mmap_control(pcm); ++ ret = map_status_and_control_data(pcm, !!sync_ptr_ioctl); + if (ret < 0) { + snd_pcm_close(pcm); + return ret; +-- +2.13.5 + + +From 812654881a370691fba3ecbd4c175c74c32b9eae Mon Sep 17 00:00:00 2001 +From: Takashi Sakamoto +Date: Sun, 25 Jun 2017 13:41:20 +0900 +Subject: [PATCH 10/39] pcm: hw: add an arrangement for initialization of + appl_ptr/avail_min + +Regardless of success/failure mapping of control/status data for runtime of +PCM substream, appl_ptr/avail_min parameters are initialized. In current +implementation, they are initialized in case-dependent, different places. +It's possible to collect them to one place. + +This commit unifies relevant code in a place after all of trials for the +mappings are finished. + +Signed-off-by: Takashi Sakamoto +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_hw.c | 42 ++++++++++++++++++++++-------------------- + 1 file changed, 22 insertions(+), 20 deletions(-) + +diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c +index abf4afe0..c60a521b 100644 +--- a/src/pcm/pcm_hw.c ++++ b/src/pcm/pcm_hw.c +@@ -867,10 +867,8 @@ static snd_pcm_sframes_t snd_pcm_hw_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_u + return xfern.result; + } + +-static int map_status_data(snd_pcm_t *pcm) ++static int map_status_data(snd_pcm_hw_t *hw) + { +- snd_pcm_hw_t *hw = pcm->private_data; +- struct snd_pcm_sync_ptr sync_ptr; + void *ptr; + int err; + ptr = MAP_FAILED; +@@ -879,15 +877,6 @@ static int map_status_data(snd_pcm_t *pcm) + PROT_READ, MAP_FILE|MAP_SHARED, + hw->fd, SNDRV_PCM_MMAP_OFFSET_STATUS); + if (ptr == MAP_FAILED || ptr == NULL) { +- memset(&sync_ptr, 0, sizeof(sync_ptr)); +- sync_ptr.c.control.appl_ptr = 0; +- sync_ptr.c.control.avail_min = 1; +- err = ioctl(hw->fd, SNDRV_PCM_IOCTL_SYNC_PTR, &sync_ptr); +- if (err < 0) { +- err = -errno; +- SYSMSG("SNDRV_PCM_IOCTL_SYNC_PTR failed (%i)", err); +- return err; +- } + hw->sync_ptr = calloc(1, sizeof(struct snd_pcm_sync_ptr)); + if (hw->sync_ptr == NULL) + return -ENOMEM; +@@ -897,13 +886,12 @@ static int map_status_data(snd_pcm_t *pcm) + } else { + hw->mmap_status = ptr; + } +- snd_pcm_set_hw_ptr(pcm, &hw->mmap_status->hw_ptr, hw->fd, SNDRV_PCM_MMAP_OFFSET_STATUS + offsetof(struct snd_pcm_mmap_status, hw_ptr)); ++ + return 0; + } + +-static int map_control_data(snd_pcm_t *pcm) ++static int map_control_data(snd_pcm_hw_t *hw) + { +- snd_pcm_hw_t *hw = pcm->private_data; + void *ptr; + int err; + if (hw->sync_ptr == NULL) { +@@ -916,10 +904,8 @@ static int map_control_data(snd_pcm_t *pcm) + return err; + } + hw->mmap_control = ptr; +- } else { +- hw->mmap_control->avail_min = 1; + } +- snd_pcm_set_appl_ptr(pcm, &hw->mmap_control->appl_ptr, hw->fd, SNDRV_PCM_MMAP_OFFSET_CONTROL); ++ + return 0; + } + +@@ -930,14 +916,30 @@ static int map_status_and_control_data(snd_pcm_t *pcm, bool force_fallback) + + hw->sync_ptr_ioctl = (int)force_fallback; + +- err = map_status_data(pcm); ++ err = map_status_data(hw); + if (err < 0) + return err; + +- err = map_control_data(pcm); ++ err = map_control_data(hw); + if (err < 0) + return err; + ++ /* Initialize the data. */ ++ hw->mmap_control->appl_ptr = 0; ++ hw->mmap_control->avail_min = 1; ++ snd_pcm_set_hw_ptr(pcm, &hw->mmap_status->hw_ptr, hw->fd, ++ SNDRV_PCM_MMAP_OFFSET_STATUS + ++ offsetof(struct snd_pcm_mmap_status, hw_ptr)); ++ snd_pcm_set_appl_ptr(pcm, &hw->mmap_control->appl_ptr, hw->fd, ++ SNDRV_PCM_MMAP_OFFSET_CONTROL); ++ if (hw->sync_ptr_ioctl) { ++ if (ioctl(hw->fd, SNDRV_PCM_IOCTL_SYNC_PTR, hw->sync_ptr) < 0) { ++ err = -errno; ++ SYSMSG("SNDRV_PCM_IOCTL_SYNC_PTR failed (%i)", err); ++ return err; ++ } ++ } ++ + return 0; + } + +-- +2.13.5 + + +From cb7503eba15714c40630d9e26bf7e5905ee3da50 Mon Sep 17 00:00:00 2001 +From: Takashi Sakamoto +Date: Sun, 25 Jun 2017 13:41:21 +0900 +Subject: [PATCH 11/39] pcm: hw: deallocate fallback buffer when trials of + unmapping finished + +In current implementation, deallocation of fallback buffer is done at +several places. + +This commit unifies these deallocations in one place. + +Signed-off-by: Takashi Sakamoto +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_hw.c | 43 +++++++++++++++++-------------------------- + 1 file changed, 17 insertions(+), 26 deletions(-) + +diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c +index c60a521b..1d34956c 100644 +--- a/src/pcm/pcm_hw.c ++++ b/src/pcm/pcm_hw.c +@@ -943,44 +943,35 @@ static int map_status_and_control_data(snd_pcm_t *pcm, bool force_fallback) + return 0; + } + +-static int unmap_status_data(snd_pcm_hw_t *hw) ++static void unmap_status_data(snd_pcm_hw_t *hw) + { +- int err; +- +- if (hw->sync_ptr_ioctl) { +- free(hw->sync_ptr); +- hw->sync_ptr = NULL; +- } else { +- if (munmap((void*)hw->mmap_status, page_align(sizeof(*hw->mmap_status))) < 0) { +- err = -errno; +- SYSMSG("status munmap failed (%i)", err); +- return err; +- } ++ if (!hw->sync_ptr) { ++ if (munmap((void *)hw->mmap_status, ++ page_align(sizeof(*hw->mmap_status))) < 0) ++ SYSMSG("status munmap failed (%u)", errno); + } +- return 0; + } + +-static int unmap_control_data(snd_pcm_hw_t *hw) ++static void unmap_control_data(snd_pcm_hw_t *hw) + { +- int err; +- +- if (hw->sync_ptr_ioctl) { +- free(hw->sync_ptr); +- hw->sync_ptr = NULL; +- } else { +- if (munmap(hw->mmap_control, page_align(sizeof(*hw->mmap_control))) < 0) { +- err = -errno; +- SYSMSG("control munmap failed (%i)", err); +- return err; +- } ++ if (!hw->sync_ptr) { ++ if (munmap((void *)hw->mmap_control, ++ page_align(sizeof(*hw->mmap_control))) < 0) ++ SYSMSG("control munmap failed (%u)", errno); + } +- return 0; + } + + static void unmap_status_and_control_data(snd_pcm_hw_t *hw) + { + unmap_status_data(hw); + unmap_control_data(hw); ++ ++ if (hw->sync_ptr) ++ free(hw->sync_ptr); ++ ++ hw->mmap_status = NULL; ++ hw->mmap_control = NULL; ++ hw->sync_ptr = NULL; + } + + static int snd_pcm_hw_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) +-- +2.13.5 + + +From afadf61e44706880c32a854648645409c82dc0a2 Mon Sep 17 00:00:00 2001 +From: Takashi Sakamoto +Date: Sun, 25 Jun 2017 13:41:22 +0900 +Subject: [PATCH 12/39] pcm: hw: allocate fallback buffer in advance of trials + of mapping + +When allowing failure of map operation for both of status/control data +for runtime of PCM substream, applications need to use fallback buffer +for an alternative ioctl. However, in current implementation, status +mapping is dominant to the allocation. + +This commit moves code for the allocation outside of the mapping +operation for status data. + +Signed-off-by: Takashi Sakamoto +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_hw.c | 30 +++++++++++++++++++++--------- + 1 file changed, 21 insertions(+), 9 deletions(-) + +diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c +index 1d34956c..a3d1f137 100644 +--- a/src/pcm/pcm_hw.c ++++ b/src/pcm/pcm_hw.c +@@ -867,21 +867,18 @@ static snd_pcm_sframes_t snd_pcm_hw_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_u + return xfern.result; + } + +-static int map_status_data(snd_pcm_hw_t *hw) ++static int map_status_data(snd_pcm_hw_t *hw, struct snd_pcm_sync_ptr *sync_ptr) + { + void *ptr; +- int err; ++ + ptr = MAP_FAILED; + if (hw->sync_ptr_ioctl == 0) + ptr = mmap(NULL, page_align(sizeof(struct snd_pcm_mmap_status)), + PROT_READ, MAP_FILE|MAP_SHARED, + hw->fd, SNDRV_PCM_MMAP_OFFSET_STATUS); + if (ptr == MAP_FAILED || ptr == NULL) { +- hw->sync_ptr = calloc(1, sizeof(struct snd_pcm_sync_ptr)); +- if (hw->sync_ptr == NULL) +- return -ENOMEM; +- hw->mmap_status = &hw->sync_ptr->s.status; +- hw->mmap_control = &hw->sync_ptr->c.control; ++ hw->mmap_status = &sync_ptr->s.status; ++ hw->mmap_control = &sync_ptr->c.control; + hw->sync_ptr_ioctl = 1; + } else { + hw->mmap_status = ptr; +@@ -894,7 +891,7 @@ static int map_control_data(snd_pcm_hw_t *hw) + { + void *ptr; + int err; +- if (hw->sync_ptr == NULL) { ++ if (hw->sync_ptr_ioctl == 0) { + ptr = mmap(NULL, page_align(sizeof(struct snd_pcm_mmap_control)), + PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, + hw->fd, SNDRV_PCM_MMAP_OFFSET_CONTROL); +@@ -912,11 +909,18 @@ static int map_control_data(snd_pcm_hw_t *hw) + static int map_status_and_control_data(snd_pcm_t *pcm, bool force_fallback) + { + snd_pcm_hw_t *hw = pcm->private_data; ++ struct snd_pcm_sync_ptr *sync_ptr; + int err; + ++ /* Preparation for fallback to failure of mmap(2). */ ++ sync_ptr = malloc(sizeof(*sync_ptr)); ++ if (sync_ptr == NULL) ++ return -ENOMEM; ++ memset(sync_ptr, 0, sizeof(*sync_ptr)); ++ + hw->sync_ptr_ioctl = (int)force_fallback; + +- err = map_status_data(hw); ++ err = map_status_data(hw, sync_ptr); + if (err < 0) + return err; + +@@ -924,6 +928,14 @@ static int map_status_and_control_data(snd_pcm_t *pcm, bool force_fallback) + if (err < 0) + return err; + ++ /* Any fallback mode needs to keep the buffer. */ ++ if (hw->sync_ptr_ioctl == 0) { ++ hw->sync_ptr = sync_ptr; ++ } else { ++ free(sync_ptr); ++ hw->sync_ptr = NULL; ++ } ++ + /* Initialize the data. */ + hw->mmap_control->appl_ptr = 0; + hw->mmap_control->avail_min = 1; +-- +2.13.5 + + +From 9c9e3d0822777b36d7c8cae21550b180d108a160 Mon Sep 17 00:00:00 2001 +From: Takashi Sakamoto +Date: Sun, 25 Jun 2017 13:41:23 +0900 +Subject: [PATCH 13/39] pcm: hw: maintain fallback mode for status data mapping + +In current implementation, results to map status/control data are not +maintained separately. It's handled as a fatal error that mapping of status +data is successful and mapping of control data is failed. However, it's +possible to handle this case by utilizing fallback buffer. + +This commit adds a member into a local structure to maintain fallback mode +just for the mapping of status data as a preparation of later commit, in +which mapping results are maintained separately for each of status/control +data. + +Signed-off-by: Takashi Sakamoto +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_hw.c | 78 ++++++++++++++++++++++++++++++++------------------------ + 1 file changed, 44 insertions(+), 34 deletions(-) + +diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c +index a3d1f137..78857941 100644 +--- a/src/pcm/pcm_hw.c ++++ b/src/pcm/pcm_hw.c +@@ -91,10 +91,12 @@ typedef struct { + int version; + int fd; + int card, device, subdevice; +- int sync_ptr_ioctl; ++ + volatile struct snd_pcm_mmap_status * mmap_status; + struct snd_pcm_mmap_control *mmap_control; ++ bool mmap_status_fallbacked; + struct snd_pcm_sync_ptr *sync_ptr; ++ + int period_event; + snd_timer_t *period_timer; + struct pollfd period_timer_pfd; +@@ -867,42 +869,53 @@ static snd_pcm_sframes_t snd_pcm_hw_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_u + return xfern.result; + } + +-static int map_status_data(snd_pcm_hw_t *hw, struct snd_pcm_sync_ptr *sync_ptr) ++static bool map_status_data(snd_pcm_hw_t *hw, struct snd_pcm_sync_ptr *sync_ptr, ++ bool force_fallback) + { +- void *ptr; ++ struct snd_pcm_mmap_status *mmap_status; ++ bool fallbacked; ++ ++ mmap_status = MAP_FAILED; ++ if (!force_fallback) { ++ mmap_status = mmap(NULL, page_align(sizeof(*mmap_status)), ++ PROT_READ, MAP_FILE|MAP_SHARED, ++ hw->fd, SNDRV_PCM_MMAP_OFFSET_STATUS); ++ } + +- ptr = MAP_FAILED; +- if (hw->sync_ptr_ioctl == 0) +- ptr = mmap(NULL, page_align(sizeof(struct snd_pcm_mmap_status)), +- PROT_READ, MAP_FILE|MAP_SHARED, +- hw->fd, SNDRV_PCM_MMAP_OFFSET_STATUS); +- if (ptr == MAP_FAILED || ptr == NULL) { +- hw->mmap_status = &sync_ptr->s.status; +- hw->mmap_control = &sync_ptr->c.control; +- hw->sync_ptr_ioctl = 1; ++ if (mmap_status == MAP_FAILED || mmap_status == NULL) { ++ mmap_status = &sync_ptr->s.status; ++ fallbacked = true; + } else { +- hw->mmap_status = ptr; ++ fallbacked = false; + } + +- return 0; ++ hw->mmap_status = mmap_status; ++ ++ return fallbacked; + } + +-static int map_control_data(snd_pcm_hw_t *hw) ++static bool map_control_data(snd_pcm_hw_t *hw, ++ struct snd_pcm_sync_ptr *sync_ptr, ++ bool force_fallback) + { +- void *ptr; ++ struct snd_pcm_mmap_control *mmap_control; + int err; +- if (hw->sync_ptr_ioctl == 0) { +- ptr = mmap(NULL, page_align(sizeof(struct snd_pcm_mmap_control)), +- PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, +- hw->fd, SNDRV_PCM_MMAP_OFFSET_CONTROL); +- if (ptr == MAP_FAILED || ptr == NULL) { ++ ++ if (!force_fallback) { ++ mmap_control = mmap(NULL, page_align(sizeof(*mmap_control)), ++ PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, ++ hw->fd, SNDRV_PCM_MMAP_OFFSET_CONTROL); ++ if (mmap_control == MAP_FAILED || mmap_control == NULL) { + err = -errno; + SYSMSG("control mmap failed (%i)", err); + return err; + } +- hw->mmap_control = ptr; ++ } else { ++ mmap_control = &sync_ptr->c.control; + } + ++ hw->mmap_control = mmap_control; ++ + return 0; + } + +@@ -918,18 +931,14 @@ static int map_status_and_control_data(snd_pcm_t *pcm, bool force_fallback) + return -ENOMEM; + memset(sync_ptr, 0, sizeof(*sync_ptr)); + +- hw->sync_ptr_ioctl = (int)force_fallback; +- +- err = map_status_data(hw, sync_ptr); +- if (err < 0) +- return err; +- +- err = map_control_data(hw); ++ hw->mmap_status_fallbacked = ++ map_status_data(hw, sync_ptr, force_fallback); ++ err = map_control_data(hw, sync_ptr, hw->mmap_status_fallbacked); + if (err < 0) + return err; + + /* Any fallback mode needs to keep the buffer. */ +- if (hw->sync_ptr_ioctl == 0) { ++ if (hw->mmap_status_fallbacked == 0) { + hw->sync_ptr = sync_ptr; + } else { + free(sync_ptr); +@@ -944,7 +953,7 @@ static int map_status_and_control_data(snd_pcm_t *pcm, bool force_fallback) + offsetof(struct snd_pcm_mmap_status, hw_ptr)); + snd_pcm_set_appl_ptr(pcm, &hw->mmap_control->appl_ptr, hw->fd, + SNDRV_PCM_MMAP_OFFSET_CONTROL); +- if (hw->sync_ptr_ioctl) { ++ if (hw->mmap_status_fallbacked) { + if (ioctl(hw->fd, SNDRV_PCM_IOCTL_SYNC_PTR, hw->sync_ptr) < 0) { + err = -errno; + SYSMSG("SNDRV_PCM_IOCTL_SYNC_PTR failed (%i)", err); +@@ -957,7 +966,7 @@ static int map_status_and_control_data(snd_pcm_t *pcm, bool force_fallback) + + static void unmap_status_data(snd_pcm_hw_t *hw) + { +- if (!hw->sync_ptr) { ++ if (!hw->mmap_status_fallbacked) { + if (munmap((void *)hw->mmap_status, + page_align(sizeof(*hw->mmap_status))) < 0) + SYSMSG("status munmap failed (%u)", errno); +@@ -966,7 +975,7 @@ static void unmap_status_data(snd_pcm_hw_t *hw) + + static void unmap_control_data(snd_pcm_hw_t *hw) + { +- if (!hw->sync_ptr) { ++ if (!hw->mmap_status_fallbacked) { + if (munmap((void *)hw->mmap_control, + page_align(sizeof(*hw->mmap_control))) < 0) + SYSMSG("control munmap failed (%u)", errno); +@@ -978,11 +987,12 @@ static void unmap_status_and_control_data(snd_pcm_hw_t *hw) + unmap_status_data(hw); + unmap_control_data(hw); + +- if (hw->sync_ptr) ++ if (hw->mmap_status_fallbacked) + free(hw->sync_ptr); + + hw->mmap_status = NULL; + hw->mmap_control = NULL; ++ hw->mmap_status_fallbacked = false; + hw->sync_ptr = NULL; + } + +-- +2.13.5 + + +From 48bf3d3e964fbd34afd430632e8f2f5ca395d24c Mon Sep 17 00:00:00 2001 +From: Takashi Sakamoto +Date: Sun, 25 Jun 2017 13:41:24 +0900 +Subject: [PATCH 14/39] pcm: hw: maintain fallback mode for control data + mapping independently + +Currently, failures of status/control data mapping are handled dependently. +However, it's not sure that one of the operations is failed when another +is failed. + +This commit adds a member into private data structure to maintain fallback +mode for control data mapping, independently of status data mapping. As a +result, we have four cases to handle status/control data: + +1. both of status/control data are mapped. +Nothing changed. A structure with alias of 'snd_pcm_hw_t' already has two +members to point the mapped area and in application runtime they're used +to refer/set status/control data. No need to call ioctl(2) with +SNDRV_PCM_IOCTL_SYNC_PTR to issue/query the data. + +2. both of status/control data are unmapped. +The two members point to allocated memory for fallback buffer. In +application runtime, the buffer is given as an argument for ioctl(2) with +SNDRV_PCM_IOCTL_SYNC_PTR to issue/query the data. + +3. status data is mapped only. +One of the two members is used to point the mapped area. Another points to +allocated memory for fallback buffer. In application runtime, the buffer +is used as an argument to execute ioctl(2) with SNDRV_PCM_IOCTL_SYNC_PTR +for the latter data, but the former data is already synchronized. + +4. control data is mapped only. +The same as the above. + +In design of ALSA PCM interface, userspace applications are not expected +to map the status data as writable. On the other hand, expected to map +the control data as writable. In a focus on the differences, we could +achieve to reduce calls of the ioctl(2) in a case that one of the +status/control data is successfully mapped and another is failed (case 3 +and 4). Especially, in current alsa-lib implementation, application +runtime queries state of runtime of PCM substream so often. + +Signed-off-by: Takashi Sakamoto +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_hw.c | 37 ++++++++++++++++++++----------------- + 1 file changed, 20 insertions(+), 17 deletions(-) + +diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c +index 78857941..5573fce2 100644 +--- a/src/pcm/pcm_hw.c ++++ b/src/pcm/pcm_hw.c +@@ -95,6 +95,7 @@ typedef struct { + volatile struct snd_pcm_mmap_status * mmap_status; + struct snd_pcm_mmap_control *mmap_control; + bool mmap_status_fallbacked; ++ bool mmap_control_fallbacked; + struct snd_pcm_sync_ptr *sync_ptr; + + int period_event; +@@ -143,9 +144,11 @@ static int sync_ptr1(snd_pcm_hw_t *hw, unsigned int flags) + return 0; + } + +-static inline int sync_ptr(snd_pcm_hw_t *hw, unsigned int flags) ++static int sync_ptr(snd_pcm_hw_t *hw, unsigned int flags) + { +- return hw->sync_ptr ? sync_ptr1(hw, flags) : 0; ++ if (hw->mmap_status_fallbacked || hw->mmap_control_fallbacked) ++ return sync_ptr1(hw, flags); ++ return 0; + } + + static int snd_pcm_hw_clear_timer_queue(snd_pcm_hw_t *hw) +@@ -899,24 +902,24 @@ static bool map_control_data(snd_pcm_hw_t *hw, + bool force_fallback) + { + struct snd_pcm_mmap_control *mmap_control; +- int err; ++ bool fallbacked; + + if (!force_fallback) { + mmap_control = mmap(NULL, page_align(sizeof(*mmap_control)), + PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, + hw->fd, SNDRV_PCM_MMAP_OFFSET_CONTROL); +- if (mmap_control == MAP_FAILED || mmap_control == NULL) { +- err = -errno; +- SYSMSG("control mmap failed (%i)", err); +- return err; +- } +- } else { ++ } ++ ++ if (mmap_control == MAP_FAILED || mmap_control == NULL) { + mmap_control = &sync_ptr->c.control; ++ fallbacked = true; ++ } else { ++ fallbacked = false; + } + + hw->mmap_control = mmap_control; + +- return 0; ++ return fallbacked; + } + + static int map_status_and_control_data(snd_pcm_t *pcm, bool force_fallback) +@@ -933,12 +936,11 @@ static int map_status_and_control_data(snd_pcm_t *pcm, bool force_fallback) + + hw->mmap_status_fallbacked = + map_status_data(hw, sync_ptr, force_fallback); +- err = map_control_data(hw, sync_ptr, hw->mmap_status_fallbacked); +- if (err < 0) +- return err; ++ hw->mmap_control_fallbacked = ++ map_control_data(hw, sync_ptr, force_fallback); + + /* Any fallback mode needs to keep the buffer. */ +- if (hw->mmap_status_fallbacked == 0) { ++ if (hw->mmap_status_fallbacked || hw->mmap_control_fallbacked) { + hw->sync_ptr = sync_ptr; + } else { + free(sync_ptr); +@@ -953,7 +955,7 @@ static int map_status_and_control_data(snd_pcm_t *pcm, bool force_fallback) + offsetof(struct snd_pcm_mmap_status, hw_ptr)); + snd_pcm_set_appl_ptr(pcm, &hw->mmap_control->appl_ptr, hw->fd, + SNDRV_PCM_MMAP_OFFSET_CONTROL); +- if (hw->mmap_status_fallbacked) { ++ if (hw->mmap_control_fallbacked) { + if (ioctl(hw->fd, SNDRV_PCM_IOCTL_SYNC_PTR, hw->sync_ptr) < 0) { + err = -errno; + SYSMSG("SNDRV_PCM_IOCTL_SYNC_PTR failed (%i)", err); +@@ -975,7 +977,7 @@ static void unmap_status_data(snd_pcm_hw_t *hw) + + static void unmap_control_data(snd_pcm_hw_t *hw) + { +- if (!hw->mmap_status_fallbacked) { ++ if (!hw->mmap_control_fallbacked) { + if (munmap((void *)hw->mmap_control, + page_align(sizeof(*hw->mmap_control))) < 0) + SYSMSG("control munmap failed (%u)", errno); +@@ -987,12 +989,13 @@ static void unmap_status_and_control_data(snd_pcm_hw_t *hw) + unmap_status_data(hw); + unmap_control_data(hw); + +- if (hw->mmap_status_fallbacked) ++ if (hw->mmap_status_fallbacked || hw->mmap_control_fallbacked) + free(hw->sync_ptr); + + hw->mmap_status = NULL; + hw->mmap_control = NULL; + hw->mmap_status_fallbacked = false; ++ hw->mmap_control_fallbacked = false; + hw->sync_ptr = NULL; + } + +-- +2.13.5 + + +From 8ef3805f1b80a6c6059e0d9efd404fe32697db15 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Tue, 20 Jun 2017 14:21:20 +0200 +Subject: [PATCH 15/39] pcm: hw: Call USER_PVERSION ioctl at open + +Up from the new PCM protocol 2.0.14, user-space can inform the +protocol version it supports to kernel, so that the kernel may switch +its behavior depending on it. Add this ioctl call in the PCM hw +plugin at opening. + +The patch contains also the addition of SNDRV_PCM_INFO_SYNC_APPLPTR +carried from the upstream kernel commit 42f945970af9 ("ALSA: pcm: Add +the explicit appl_ptr sync support"), as well as the trivial change +(an addition of comma) to sync with the kernel asound.h. + +Reviewed-by: Takashi Sakamoto +Tested-by: Takashi Sakamoto +Signed-off-by: Takashi Iwai +--- + include/sound/asound.h | 6 ++++-- + src/pcm/pcm_hw.c | 10 ++++++++++ + 2 files changed, 14 insertions(+), 2 deletions(-) + +diff --git a/include/sound/asound.h b/include/sound/asound.h +index fb8d7d7e..1949923a 100644 +--- a/include/sound/asound.h ++++ b/include/sound/asound.h +@@ -111,7 +111,7 @@ enum { + SNDRV_HWDEP_IFACE_FW_FIREFACE, /* RME Fireface series */ + + /* Don't forget to change the following: */ +- SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_FW_FIREFACE, ++ SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_FW_FIREFACE + }; + + struct snd_hwdep_info { +@@ -152,7 +152,7 @@ struct snd_hwdep_dsp_image { + * * + *****************************************************************************/ + +-#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 13) ++#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 14) + + typedef unsigned long snd_pcm_uframes_t; + typedef signed long snd_pcm_sframes_t; +@@ -268,6 +268,7 @@ typedef int __bitwise snd_pcm_subformat_t; + #define SNDRV_PCM_INFO_MMAP_VALID 0x00000002 /* period data are valid during transfer */ + #define SNDRV_PCM_INFO_DOUBLE 0x00000004 /* Double buffering needed for PCM start/stop */ + #define SNDRV_PCM_INFO_BATCH 0x00000010 /* double buffering */ ++#define SNDRV_PCM_INFO_SYNC_APPLPTR 0x00000020 /* need the explicit sync of appl_ptr update */ + #define SNDRV_PCM_INFO_INTERLEAVED 0x00000100 /* channels are interleaved */ + #define SNDRV_PCM_INFO_NONINTERLEAVED 0x00000200 /* channels are not interleaved */ + #define SNDRV_PCM_INFO_COMPLEX 0x00000400 /* complex frame organization (mmap only) */ +@@ -563,6 +564,7 @@ enum { + #define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct snd_pcm_info) + #define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int) + #define SNDRV_PCM_IOCTL_TTSTAMP _IOW('A', 0x03, int) ++#define SNDRV_PCM_IOCTL_USER_PVERSION _IOW('A', 0x04, int) + #define SNDRV_PCM_IOCTL_HW_REFINE _IOWR('A', 0x10, struct snd_pcm_hw_params) + #define SNDRV_PCM_IOCTL_HW_PARAMS _IOWR('A', 0x11, struct snd_pcm_hw_params) + #define SNDRV_PCM_IOCTL_HW_FREE _IO('A', 0x12) +diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c +index 5573fce2..64188b22 100644 +--- a/src/pcm/pcm_hw.c ++++ b/src/pcm/pcm_hw.c +@@ -1494,6 +1494,16 @@ int snd_pcm_hw_open_fd(snd_pcm_t **pcmp, const char *name, int fd, + if (SNDRV_PROTOCOL_INCOMPATIBLE(ver, SNDRV_PCM_VERSION_MAX)) + return -SND_ERROR_INCOMPATIBLE_VERSION; + ++ if (SNDRV_PROTOCOL_VERSION(2, 0, 14) <= ver) { ++ /* inform the protocol version we're supporting */ ++ unsigned int user_ver = SNDRV_PCM_VERSION; ++ if (ioctl(fd, SNDRV_PCM_IOCTL_USER_PVERSION, &user_ver) < 0) { ++ ret = -errno; ++ SNDMSG("USER_PVERSION failed\n"); ++ return ret; ++ } ++ } ++ + #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) + if (SNDRV_PROTOCOL_VERSION(2, 0, 9) <= ver) { + struct timespec timespec; +-- +2.13.5 + + +From ec16d21f86abbc23a56abeed0419a5a863ee5400 Mon Sep 17 00:00:00 2001 +From: Takashi Sakamoto +Date: Fri, 30 Jun 2017 19:50:00 +0900 +Subject: [PATCH 16/39] pcm: hw: fix to initialize function local variable +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This commit is to fix below warning. + +pcm_hw.c: In function ‘snd1_pcm_hw_open_fd’: +pcm_hw.c:955:33: warning: ‘mmap_control’ may be used uninitialized in this function [-Wmaybe-uninitialized] + if (mmap_control == MAP_FAILED || mmap_control == NULL) { + ^ +pcm_hw.c:946:31: note: ‘mmap_control’ was declared here + struct snd_pcm_mmap_control *mmap_control; + ^~~~~~~~~~~~ + +Signed-off-by: Takashi Sakamoto +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_hw.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c +index 64188b22..e0931577 100644 +--- a/src/pcm/pcm_hw.c ++++ b/src/pcm/pcm_hw.c +@@ -904,6 +904,7 @@ static bool map_control_data(snd_pcm_hw_t *hw, + struct snd_pcm_mmap_control *mmap_control; + bool fallbacked; + ++ mmap_control = MAP_FAILED; + if (!force_fallback) { + mmap_control = mmap(NULL, page_align(sizeof(*mmap_control)), + PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, +-- +2.13.5 + + +From 84beecc71ec508feb32bdf3fd1655dc7d0badfac Mon Sep 17 00:00:00 2001 +From: Liam Girdwood +Date: Fri, 30 Jun 2017 14:14:55 +0100 +Subject: [PATCH 17/39] topology: Add support for new widget types + +Add topology support for new DSP widget types. This allows the new +widgets to be added to the driver and firmware DAPM graphs. + +Signed-off-by: Liam Girdwood +Signed-off-by: Takashi Iwai +--- + include/sound/asoc.h | 10 +++++++++- + src/topology/dapm.c | 8 ++++++++ + 2 files changed, 17 insertions(+), 1 deletion(-) + +diff --git a/include/sound/asoc.h b/include/sound/asoc.h +index 082c5429..0f5d9f9a 100644 +--- a/include/sound/asoc.h ++++ b/include/sound/asoc.h +@@ -70,7 +70,15 @@ + #define SND_SOC_TPLG_DAPM_DAI_IN 13 + #define SND_SOC_TPLG_DAPM_DAI_OUT 14 + #define SND_SOC_TPLG_DAPM_DAI_LINK 15 +-#define SND_SOC_TPLG_DAPM_LAST SND_SOC_TPLG_DAPM_DAI_LINK ++#define SND_SOC_TPLG_DAPM_BUFFER 16 ++#define SND_SOC_TPLG_DAPM_SCHEDULER 17 ++#define SND_SOC_TPLG_DAPM_EFFECT 18 ++#define SND_SOC_TPLG_DAPM_SIGGEN 19 ++#define SND_SOC_TPLG_DAPM_SRC 20 ++#define SND_SOC_TPLG_DAPM_ASRC 21 ++#define SND_SOC_TPLG_DAPM_ENCODER 22 ++#define SND_SOC_TPLG_DAPM_DECODER 23 ++#define SND_SOC_TPLG_DAPM_LAST SND_SOC_TPLG_DAPM_DECODER + + /* Header magic number and string sizes */ + #define SND_SOC_TPLG_MAGIC 0x41536F43 /* ASoC */ +diff --git a/src/topology/dapm.c b/src/topology/dapm.c +index 6af750b9..66892a66 100644 +--- a/src/topology/dapm.c ++++ b/src/topology/dapm.c +@@ -38,6 +38,14 @@ static const struct map_elem widget_map[] = { + {"dai_in", SND_SOC_TPLG_DAPM_DAI_IN}, + {"dai_out", SND_SOC_TPLG_DAPM_DAI_OUT}, + {"dai_link", SND_SOC_TPLG_DAPM_DAI_LINK}, ++ {"buffer", SND_SOC_TPLG_DAPM_BUFFER}, ++ {"scheduler", SND_SOC_TPLG_DAPM_SCHEDULER}, ++ {"effect", SND_SOC_TPLG_DAPM_EFFECT}, ++ {"siggen", SND_SOC_TPLG_DAPM_SIGGEN}, ++ {"src", SND_SOC_TPLG_DAPM_SRC}, ++ {"asrc", SND_SOC_TPLG_DAPM_ASRC}, ++ {"encoder", SND_SOC_TPLG_DAPM_ENCODER}, ++ {"decoder", SND_SOC_TPLG_DAPM_DECODER}, + }; + + static int lookup_widget(const char *w) +-- +2.13.5 + + +From 5c9582b8b428f3dbacb9e2fc32924f55c38efe8d Mon Sep 17 00:00:00 2001 +From: Liam Girdwood +Date: Fri, 30 Jun 2017 14:14:56 +0100 +Subject: [PATCH 18/39] topology: improve verbose output for block output. + +Show index and full DAPm route in verbose output. + +Signed-off-by: Liam Girdwood +Signed-off-by: Takashi Iwai +--- + src/topology/builder.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/src/topology/builder.c b/src/topology/builder.c +index ca5cbe1a..997df0c7 100644 +--- a/src/topology/builder.c ++++ b/src/topology/builder.c +@@ -67,9 +67,10 @@ static int write_block_header(snd_tplg_t *tplg, unsigned int type, + exit(-EINVAL); + } + +- verbose(tplg, " header type %d size 0x%lx/%ld vendor %d " +- "version %d\n", type, (long unsigned int)payload_size, +- (long int)payload_size, vendor_type, version); ++ verbose(tplg, " header index %d type %d count %d size 0x%lx/%ld vendor %d " ++ "version %d\n", index, type, count, ++ (long unsigned int)payload_size, (long int)payload_size, ++ vendor_type, version); + + tplg->next_hdr_pos += hdr.payload_size + sizeof(hdr); + +@@ -119,8 +120,10 @@ static int write_elem_block(snd_tplg_t *tplg, + verbose(tplg, " %s '%s': write %d bytes\n", + obj_name, elem->id, elem->size); + else +- verbose(tplg, " %s '%s': write %d bytes\n", +- obj_name, elem->route->source, elem->size); ++ verbose(tplg, " %s '%s -> %s -> %s': write %d bytes\n", ++ obj_name, elem->route->source, ++ elem->route->control, ++ elem->route->sink, elem->size); + + wsize = write(tplg->out_fd, elem->obj, elem->size); + if (wsize < 0) { +-- +2.13.5 + + +From 4396c83a4d572c32e88a6eb9d3f48240bf89da8e Mon Sep 17 00:00:00 2001 +From: Takashi Sakamoto +Date: Fri, 30 Jun 2017 20:00:26 +0900 +Subject: [PATCH 19/39] pcm: hw: minor refactoring for initialization of + control data + +At failure of control data mapping, alsa-lib goes to fallback mode. In +this mode, a buffer is kept in user space and executes ioctl(2) with +SNDRV_PCM_IOCTL_SYNC_PTR for the buffer to synchronize the control data. + +In current implementation, no helper function is used for initialize +the control data. This commit use an proper helper function instead of +a direct call of ioctl(2). + +Signed-off-by: Takashi Sakamoto +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_hw.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c +index e0931577..f03bc589 100644 +--- a/src/pcm/pcm_hw.c ++++ b/src/pcm/pcm_hw.c +@@ -957,11 +957,9 @@ static int map_status_and_control_data(snd_pcm_t *pcm, bool force_fallback) + snd_pcm_set_appl_ptr(pcm, &hw->mmap_control->appl_ptr, hw->fd, + SNDRV_PCM_MMAP_OFFSET_CONTROL); + if (hw->mmap_control_fallbacked) { +- if (ioctl(hw->fd, SNDRV_PCM_IOCTL_SYNC_PTR, hw->sync_ptr) < 0) { +- err = -errno; +- SYSMSG("SNDRV_PCM_IOCTL_SYNC_PTR failed (%i)", err); ++ err = sync_ptr1(hw, 0); ++ if (err < 0) + return err; +- } + } + + return 0; +-- +2.13.5 + + +From ce0905c3ca50e143cadf7b0b70f3049ef8024dab Mon Sep 17 00:00:00 2001 +From: Takashi Sakamoto +Date: Fri, 30 Jun 2017 20:37:24 +0900 +Subject: [PATCH 20/39] pcm: hw: add a helper function to query status/control + data + +When executing ioctl(2) with some commands, applications can request +ALSA PCM core to change appl_ptr in kernel space. Below is a list of +such operations: + - SNDRV_PCM_IOCTL_PREPARE + - SNDRV_PCM_IOCTL_RESET + - SNDRV_PCM_IOCTL_REWIND + - SNDRV_PCM_IOCTL_FORWARD + - SNDRV_PCM_IOCTL_WRITEI_FRAMES + - SNDRV_PCM_IOCTL_WRITEN_FRAMES + - SNDRV_PCM_IOCTL_READI_FRAMES + - SNDRV_PCM_IOCTL_READN_FRAMES + +After these operations, the value of appl_ptr should be synchronized +between kernel/user spaces. + +This commit adds a helper function to query status and control data +without issuing the control data just in fallback from failure of control +mapping. + +Signed-off-by: Takashi Sakamoto +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_hw.c | 46 ++++++++++++++++++++++++++++++++++------------ + 1 file changed, 34 insertions(+), 12 deletions(-) + +diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c +index f03bc589..9963523c 100644 +--- a/src/pcm/pcm_hw.c ++++ b/src/pcm/pcm_hw.c +@@ -151,6 +151,20 @@ static int sync_ptr(snd_pcm_hw_t *hw, unsigned int flags) + return 0; + } + ++static int query_status_and_control_data(snd_pcm_hw_t *hw) ++{ ++ if (!hw->mmap_control_fallbacked) ++ return 0; ++ ++ /* ++ * Query both of control/status data to avoid unexpected change of ++ * control data in kernel space. ++ */ ++ return sync_ptr1(hw, ++ SNDRV_PCM_SYNC_PTR_APPL | ++ SNDRV_PCM_SYNC_PTR_AVAIL_MIN); ++} ++ + static int snd_pcm_hw_clear_timer_queue(snd_pcm_hw_t *hw) + { + if (hw->period_timer_need_poll) { +@@ -601,7 +615,7 @@ static int snd_pcm_hw_prepare(snd_pcm_t *pcm) + SYSMSG("SNDRV_PCM_IOCTL_PREPARE failed (%i)", err); + return err; + } +- return sync_ptr(hw, SNDRV_PCM_SYNC_PTR_APPL); ++ return query_status_and_control_data(hw); + } + + static int snd_pcm_hw_reset(snd_pcm_t *pcm) +@@ -613,7 +627,7 @@ static int snd_pcm_hw_reset(snd_pcm_t *pcm) + SYSMSG("SNDRV_PCM_IOCTL_RESET failed (%i)", err); + return err; + } +- return sync_ptr(hw, SNDRV_PCM_SYNC_PTR_APPL); ++ return query_status_and_control_data(hw); + } + + static int snd_pcm_hw_start(snd_pcm_t *pcm) +@@ -688,7 +702,7 @@ static snd_pcm_sframes_t snd_pcm_hw_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t fra + SYSMSG("SNDRV_PCM_IOCTL_REWIND failed (%i)", err); + return err; + } +- err = sync_ptr(hw, SNDRV_PCM_SYNC_PTR_APPL); ++ err = query_status_and_control_data(hw); + if (err < 0) + return err; + return frames; +@@ -709,7 +723,7 @@ static snd_pcm_sframes_t snd_pcm_hw_forward(snd_pcm_t *pcm, snd_pcm_uframes_t fr + SYSMSG("SNDRV_PCM_IOCTL_FORWARD failed (%i)", err); + return err; + } +- err = sync_ptr(hw, SNDRV_PCM_SYNC_PTR_APPL); ++ err = query_status_and_control_data(hw); + if (err < 0) + return err; + return frames; +@@ -805,8 +819,10 @@ static snd_pcm_sframes_t snd_pcm_hw_writei(snd_pcm_t *pcm, const void *buffer, s + xferi.buf = (char*) buffer; + xferi.frames = size; + xferi.result = 0; /* make valgrind happy */ +- err = ioctl(fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &xferi); +- err = err >= 0 ? sync_ptr(hw, SNDRV_PCM_SYNC_PTR_APPL) : -errno; ++ if (ioctl(fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &xferi) < 0) ++ err = -errno; ++ else ++ err = query_status_and_control_data(hw); + #ifdef DEBUG_RW + fprintf(stderr, "hw_writei: frames = %li, xferi.result = %li, err = %i\n", size, xferi.result, err); + #endif +@@ -824,8 +840,10 @@ static snd_pcm_sframes_t snd_pcm_hw_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_ + memset(&xfern, 0, sizeof(xfern)); /* make valgrind happy */ + xfern.bufs = bufs; + xfern.frames = size; +- err = ioctl(fd, SNDRV_PCM_IOCTL_WRITEN_FRAMES, &xfern); +- err = err >= 0 ? sync_ptr(hw, SNDRV_PCM_SYNC_PTR_APPL) : -errno; ++ if (ioctl(fd, SNDRV_PCM_IOCTL_WRITEN_FRAMES, &xfern) < 0) ++ err = -errno; ++ else ++ err = query_status_and_control_data(hw); + #ifdef DEBUG_RW + fprintf(stderr, "hw_writen: frames = %li, result = %li, err = %i\n", size, xfern.result, err); + #endif +@@ -843,8 +861,10 @@ static snd_pcm_sframes_t snd_pcm_hw_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_ + xferi.buf = buffer; + xferi.frames = size; + xferi.result = 0; /* make valgrind happy */ +- err = ioctl(fd, SNDRV_PCM_IOCTL_READI_FRAMES, &xferi); +- err = err >= 0 ? sync_ptr(hw, SNDRV_PCM_SYNC_PTR_APPL) : -errno; ++ if (ioctl(fd, SNDRV_PCM_IOCTL_READI_FRAMES, &xferi) < 0) ++ err = -errno; ++ else ++ err = query_status_and_control_data(hw); + #ifdef DEBUG_RW + fprintf(stderr, "hw_readi: frames = %li, result = %li, err = %i\n", size, xferi.result, err); + #endif +@@ -862,8 +882,10 @@ static snd_pcm_sframes_t snd_pcm_hw_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_u + memset(&xfern, 0, sizeof(xfern)); /* make valgrind happy */ + xfern.bufs = bufs; + xfern.frames = size; +- err = ioctl(fd, SNDRV_PCM_IOCTL_READN_FRAMES, &xfern); +- err = err >= 0 ? sync_ptr(hw, SNDRV_PCM_SYNC_PTR_APPL) : -errno; ++ if (ioctl(fd, SNDRV_PCM_IOCTL_READN_FRAMES, &xfern) < 0) ++ err = -errno; ++ else ++ err = query_status_and_control_data(hw); + #ifdef DEBUG_RW + fprintf(stderr, "hw_readn: frames = %li, result = %li, err = %i\n", size, xfern.result, err); + #endif +-- +2.13.5 + + +From 78f3165a9e82d6f5e83e0e7075cdd96b49f9f401 Mon Sep 17 00:00:00 2001 +From: Takashi Sakamoto +Date: Fri, 30 Jun 2017 20:37:25 +0900 +Subject: [PATCH 21/39] pcm: hw: add a helper function just to query status + data + +When mapping status data successfully, mapped page includes status data +for applications. In this case, applications have no need to call ioctl(2) +with SNDRV_PCM_IOCTL_SYNC_PTR. However, in current implementation, when +map of control data is unavailable, applications execute the ioctl(2). +This is inconvenient for some cases that applications require to query +status only. + +This commit adds a helper function to query status data without issuing +the control in fallback mode from failure of status mmap. + +Signed-off-by: Takashi Sakamoto +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_hw.c | 20 +++++++++++++++++--- + 1 file changed, 17 insertions(+), 3 deletions(-) + +diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c +index 9963523c..38d975af 100644 +--- a/src/pcm/pcm_hw.c ++++ b/src/pcm/pcm_hw.c +@@ -165,6 +165,20 @@ static int query_status_and_control_data(snd_pcm_hw_t *hw) + SNDRV_PCM_SYNC_PTR_AVAIL_MIN); + } + ++static int query_status_data(snd_pcm_hw_t *hw) ++{ ++ if (!hw->mmap_status_fallbacked) ++ return 0; ++ ++ /* ++ * Query both of control/status data to avoid unexpected change of ++ * control data in kernel space. ++ */ ++ return sync_ptr1(hw, ++ SNDRV_PCM_SYNC_PTR_APPL | ++ SNDRV_PCM_SYNC_PTR_AVAIL_MIN); ++} ++ + static int snd_pcm_hw_clear_timer_queue(snd_pcm_hw_t *hw) + { + if (hw->period_timer_need_poll) { +@@ -349,7 +363,7 @@ static int snd_pcm_hw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) + params->info &= ~0xf0000000; + if (pcm->tstamp_type != SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY) + params->info |= SND_PCM_INFO_MONOTONIC; +- return sync_ptr(hw, 0); ++ return query_status_data(hw); + } + + static void snd_pcm_hw_close_timer(snd_pcm_hw_t *hw) +@@ -556,7 +570,7 @@ static int snd_pcm_hw_status(snd_pcm_t *pcm, snd_pcm_status_t * status) + static snd_pcm_state_t snd_pcm_hw_state(snd_pcm_t *pcm) + { + snd_pcm_hw_t *hw = pcm->private_data; +- int err = sync_ptr(hw, 0); ++ int err = query_status_data(hw); + if (err < 0) + return err; + return (snd_pcm_state_t) hw->mmap_status->state; +@@ -1064,7 +1078,7 @@ static snd_pcm_sframes_t snd_pcm_hw_avail_update(snd_pcm_t *pcm) + snd_pcm_hw_t *hw = pcm->private_data; + snd_pcm_uframes_t avail; + +- sync_ptr(hw, 0); ++ query_status_data(hw); + avail = snd_pcm_mmap_avail(pcm); + switch (FAST_PCM_STATE(hw)) { + case SNDRV_PCM_STATE_RUNNING: +-- +2.13.5 + + +From 8a3df40bce2ae3fd9e9dfdf979b2c672754e0b93 Mon Sep 17 00:00:00 2001 +From: Takashi Sakamoto +Date: Fri, 30 Jun 2017 20:37:26 +0900 +Subject: [PATCH 22/39] pcm: hw: add a helper function to request hwsync + without side-effects + +SNDRV_PCM_IOCTL_SYNC_PTR command for ioctl(2) with +SNDRV_PCM_SYNC_PTR_HWSYNC flag has an effect to update hw_ptr. +This is an alternative of SNDRV_PCM_IOCTL_HWSYNC but caller can get +current status simultaneously. + +This commit adds a helper function just to issue hwsync. To avoid +side-effect to change appl_ptr and avail_min, this commit uses +SNDRV_PCM_SYNC_PTR_APPL and SNDRV_PCM_SYNC_PTR_AVAIL_MIN flags. + +Signed-off-by: Takashi Sakamoto +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_hw.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c +index 38d975af..8455baaf 100644 +--- a/src/pcm/pcm_hw.c ++++ b/src/pcm/pcm_hw.c +@@ -151,6 +151,21 @@ static int sync_ptr(snd_pcm_hw_t *hw, unsigned int flags) + return 0; + } + ++static int request_hwsync(snd_pcm_hw_t *hw) ++{ ++ if (!hw->mmap_status_fallbacked) ++ return 0; ++ ++ /* ++ * Query both of control/status data to avoid unexpected change of ++ * control data in kernel space. ++ */ ++ return sync_ptr1(hw, ++ SNDRV_PCM_SYNC_PTR_HWSYNC | ++ SNDRV_PCM_SYNC_PTR_APPL | ++ SNDRV_PCM_SYNC_PTR_AVAIL_MIN); ++} ++ + static int query_status_and_control_data(snd_pcm_hw_t *hw) + { + if (!hw->mmap_control_fallbacked) +@@ -593,8 +608,8 @@ static int snd_pcm_hw_hwsync(snd_pcm_t *pcm) + snd_pcm_hw_t *hw = pcm->private_data; + int fd = hw->fd, err; + if (SNDRV_PROTOCOL_VERSION(2, 0, 3) <= hw->version) { +- if (hw->sync_ptr) { +- err = sync_ptr1(hw, SNDRV_PCM_SYNC_PTR_HWSYNC); ++ if (hw->mmap_status_fallbacked) { ++ err = request_hwsync(hw); + if (err < 0) + return err; + } else { +-- +2.13.5 + + +From de9fe69e40e6b705aeae9aa8d1408736d4a1e563 Mon Sep 17 00:00:00 2001 +From: Takashi Sakamoto +Date: Fri, 30 Jun 2017 20:37:27 +0900 +Subject: [PATCH 23/39] pcm: hw: add a helper function to issue appl_ptr + without side-effects + +After starting, PCM substream shift its state to running and applications +can move appl_ptr by several ways. When status and control data of runtime +of the PCM substream is not mapped, the applications should issue appl_ptr +to kernel land. In this case, when any PCM frames is handled by mmap +operation, the applications should issue appl_ptr to update. + +This commit adds a helper function for this purpose. To avoid unexpected +change of avail_min, this commit uses a flag just to update appl_ptr. + +Signed-off-by: Takashi Sakamoto +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_hw.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c +index 8455baaf..51512306 100644 +--- a/src/pcm/pcm_hw.c ++++ b/src/pcm/pcm_hw.c +@@ -151,6 +151,15 @@ static int sync_ptr(snd_pcm_hw_t *hw, unsigned int flags) + return 0; + } + ++static int issue_applptr(snd_pcm_hw_t *hw) ++{ ++ if (!hw->mmap_control_fallbacked) ++ return 0; ++ ++ /* Avoid unexpected change of avail_min in kernel space. */ ++ return sync_ptr1(hw, SNDRV_PCM_SYNC_PTR_AVAIL_MIN); ++} ++ + static int request_hwsync(snd_pcm_hw_t *hw) + { + if (!hw->mmap_status_fallbacked) +@@ -667,7 +676,7 @@ static int snd_pcm_hw_start(snd_pcm_t *pcm) + assert(pcm->stream != SND_PCM_STREAM_PLAYBACK || + snd_pcm_mmap_playback_hw_avail(pcm) > 0); + #endif +- sync_ptr(hw, 0); ++ issue_applptr(hw); + if (ioctl(hw->fd, SNDRV_PCM_IOCTL_START) < 0) { + err = -errno; + SYSMSG("SNDRV_PCM_IOCTL_START failed (%i)", err); +@@ -1081,7 +1090,7 @@ static snd_pcm_sframes_t snd_pcm_hw_mmap_commit(snd_pcm_t *pcm, + snd_pcm_hw_t *hw = pcm->private_data; + + snd_pcm_mmap_appl_forward(pcm, size); +- sync_ptr(hw, 0); ++ issue_applptr(hw); + #ifdef DEBUG_MMAP + fprintf(stderr, "appl_forward: hw_ptr = %li, appl_ptr = %li, size = %li\n", *pcm->hw.ptr, *pcm->appl.ptr, size); + #endif +-- +2.13.5 + + +From cea81cbdc2e7be344a34992ad6adef451a759840 Mon Sep 17 00:00:00 2001 +From: Takashi Sakamoto +Date: Fri, 30 Jun 2017 20:37:28 +0900 +Subject: [PATCH 24/39] pcm: hw: add a helper function to issue avail_min + without side-effects + +At present, applications can change avail_min parameter of PCM substream +by two ways; via mapped control data, and by executing ioctl(2) with +SNDRV_PCM_IOCTL_SYNC_PTR. The former is available in a case that the +applications map the data successfully. + +When utilizing alsa-lib API, the above is done by a call of +'snd_pcm_sw_params()' to hw PCM plugin. In current implementation, this +call has an side-effect to issue appl_ptr unexpectedly. + +This commit adds a helper function to issue avail_min without the +side-effect. + +Signed-off-by: Takashi Sakamoto +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_hw.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c +index 51512306..9c8fc3f6 100644 +--- a/src/pcm/pcm_hw.c ++++ b/src/pcm/pcm_hw.c +@@ -151,6 +151,15 @@ static int sync_ptr(snd_pcm_hw_t *hw, unsigned int flags) + return 0; + } + ++static int issue_avail_min(snd_pcm_hw_t *hw) ++{ ++ if (!hw->mmap_control_fallbacked) ++ return 0; ++ ++ /* Avoid unexpected change of applptr in kernel space. */ ++ return sync_ptr1(hw, SNDRV_PCM_SYNC_PTR_APPL); ++} ++ + static int issue_applptr(snd_pcm_hw_t *hw) + { + if (!hw->mmap_control_fallbacked) +@@ -506,7 +515,7 @@ static int snd_pcm_hw_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params) + params->silence_size == pcm->silence_size && + old_period_event == hw->period_event) { + hw->mmap_control->avail_min = params->avail_min; +- return sync_ptr(hw, 0); ++ return issue_avail_min(hw); + } + if (params->tstamp_type == SND_PCM_TSTAMP_TYPE_MONOTONIC_RAW && + hw->version < SNDRV_PROTOCOL_VERSION(2, 0, 12)) { +-- +2.13.5 + + +From a9ec1a6f687a6cb4f14d3f093c2ee020b610e12d Mon Sep 17 00:00:00 2001 +From: Takashi Sakamoto +Date: Fri, 30 Jun 2017 20:37:29 +0900 +Subject: [PATCH 25/39] pcm: hw: remove superfluous code to call of + SNDRV_PCM_IOCTL_SYNC_PTR in snd_pcm_hw_forward() + +SNDRV_PCM_IOCTL_SYNC_PTR command was introduced to PCM protocol/interface +in its version 2.0.7, however this command is used in a branch for the +newer version protocol/interface in snd_pcm_hw_forward(). + +This commit removes the superfluous code as a part of work for code +refactoring. + +Fixes: eafb4925124b ("- added SYNC_PTR ioctl support for pcm_hw plugin") +Signed-off-by: Takashi Sakamoto +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_hw.c | 13 ------------- + 1 file changed, 13 deletions(-) + +diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c +index 9c8fc3f6..16d45e74 100644 +--- a/src/pcm/pcm_hw.c ++++ b/src/pcm/pcm_hw.c +@@ -144,13 +144,6 @@ static int sync_ptr1(snd_pcm_hw_t *hw, unsigned int flags) + return 0; + } + +-static int sync_ptr(snd_pcm_hw_t *hw, unsigned int flags) +-{ +- if (hw->mmap_status_fallbacked || hw->mmap_control_fallbacked) +- return sync_ptr1(hw, flags); +- return 0; +-} +- + static int issue_avail_min(snd_pcm_hw_t *hw) + { + if (!hw->mmap_control_fallbacked) +@@ -777,9 +770,6 @@ static snd_pcm_sframes_t snd_pcm_hw_forward(snd_pcm_t *pcm, snd_pcm_uframes_t fr + } else { + snd_pcm_sframes_t avail; + +- err = sync_ptr(hw, SNDRV_PCM_SYNC_PTR_HWSYNC); +- if (err < 0) +- return err; + switch (FAST_PCM_STATE(hw)) { + case SNDRV_PCM_STATE_RUNNING: + case SNDRV_PCM_STATE_DRAINING: +@@ -797,9 +787,6 @@ static snd_pcm_sframes_t snd_pcm_hw_forward(snd_pcm_t *pcm, snd_pcm_uframes_t fr + if (frames > (snd_pcm_uframes_t)avail) + frames = avail; + snd_pcm_mmap_appl_forward(pcm, frames); +- err = sync_ptr(hw, 0); +- if (err < 0) +- return err; + return frames; + } + } +-- +2.13.5 + + +From 885c64bcc48f5734da964d2da2b9a5603d7b2c8b Mon Sep 17 00:00:00 2001 +From: Natanael Copa +Date: Wed, 12 Jul 2017 10:45:18 +0200 +Subject: [PATCH 26/39] cleanup: fix poll.h includes + +According POSIX[1] and linux manpage[2] the include is poll.h, not +sys/poll.h. + +This fixes the he following compiler warning when build with musl libc: + + /usr/include/sys/poll.h:1:2: warning: #warning redirecting incorrect #include to [-Wcpp] + #warning redirecting incorrect #include to + ^~~~~~~ + +Signed-off-by: Natanael Copa +Signed-off-by: Takashi Iwai +--- + aserver/aserver.c | 2 +- + include/asoundlib-head.h | 2 +- + include/local.h | 2 +- + src/control/control.c | 2 +- + src/control/control_shm.c | 2 +- + src/pcm/pcm.c | 2 +- + src/pcm/pcm_direct.c | 2 +- + src/pcm/pcm_mmap.c | 2 +- + src/pcm/pcm_share.c | 2 +- + src/pcm/pcm_shm.c | 2 +- + src/seq/seq.c | 2 +- + src/shmarea.c | 2 +- + 12 files changed, 12 insertions(+), 12 deletions(-) + +diff --git a/aserver/aserver.c b/aserver/aserver.c +index ac20706b..46f731a4 100644 +--- a/aserver/aserver.c ++++ b/aserver/aserver.c +@@ -20,7 +20,7 @@ + + #include + #include +-#include ++#include + #include + #include + #include +diff --git a/include/asoundlib-head.h b/include/asoundlib-head.h +index 1ec611e5..21e32c6b 100644 +--- a/include/asoundlib-head.h ++++ b/include/asoundlib-head.h +@@ -35,6 +35,6 @@ + #include + #include + #include +-#include ++#include + #include + #include +diff --git a/include/local.h b/include/local.h +index 317f2e32..6a43a473 100644 +--- a/include/local.h ++++ b/include/local.h +@@ -47,7 +47,7 @@ + #error Header defining endianness not defined + #endif + #include +-#include ++#include + #include + #include + #if defined(__linux__) +diff --git a/src/control/control.c b/src/control/control.c +index 134ba4c8..6439b294 100644 +--- a/src/control/control.c ++++ b/src/control/control.c +@@ -90,7 +90,7 @@ against the original design. + #include + #include + #include +-#include ++#include + #include + #include "control_local.h" + +diff --git a/src/control/control_shm.c b/src/control/control_shm.c +index bd07d4af..9a2e268b 100644 +--- a/src/control/control_shm.c ++++ b/src/control/control_shm.c +@@ -27,7 +27,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include +diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c +index 200b10c2..2b4ce8ec 100644 +--- a/src/pcm/pcm.c ++++ b/src/pcm/pcm.c +@@ -651,7 +651,7 @@ playback devices. + #include + #include + #include +-#include ++#include + #include + #include + #include "pcm_local.h" +diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c +index 9fd376d8..393083f5 100644 +--- a/src/pcm/pcm_direct.c ++++ b/src/pcm/pcm_direct.c +@@ -30,7 +30,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include +diff --git a/src/pcm/pcm_mmap.c b/src/pcm/pcm_mmap.c +index 1948289c..4cf220a4 100644 +--- a/src/pcm/pcm_mmap.c ++++ b/src/pcm/pcm_mmap.c +@@ -22,7 +22,7 @@ + #include + #include + #include +-#include ++#include + #include + #ifdef HAVE_SYS_SHM_H + #include +diff --git a/src/pcm/pcm_share.c b/src/pcm/pcm_share.c +index 5d8aaf21..21a57fc6 100644 +--- a/src/pcm/pcm_share.c ++++ b/src/pcm/pcm_share.c +@@ -34,7 +34,7 @@ + #include + #include + #include +-#include ++#include + #include + #include "pcm_local.h" + +diff --git a/src/pcm/pcm_shm.c b/src/pcm/pcm_shm.c +index a815ac6b..4ee958c1 100644 +--- a/src/pcm/pcm_shm.c ++++ b/src/pcm/pcm_shm.c +@@ -36,7 +36,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include +diff --git a/src/seq/seq.c b/src/seq/seq.c +index b206e2f8..d5ed1c6a 100644 +--- a/src/seq/seq.c ++++ b/src/seq/seq.c +@@ -777,7 +777,7 @@ void event_filter(snd_seq_t *seq, snd_seq_event_t *ev) + + */ + +-#include ++#include + #include "seq_local.h" + + /**************************************************************************** +diff --git a/src/shmarea.c b/src/shmarea.c +index 9843aa8b..eaa71f00 100644 +--- a/src/shmarea.c ++++ b/src/shmarea.c +@@ -27,7 +27,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include "list.h" +-- +2.13.5 + + +From adab355f35c8fcb424b1336043634cf9a6856515 Mon Sep 17 00:00:00 2001 +From: Natanael Copa +Date: Fri, 14 Jul 2017 16:18:11 +0200 +Subject: [PATCH 27/39] cleanup: Use uint*_t instead of u_int*_t everythwere + +Use the standard uint{8,16,32,64}_t everywhere instead of the +non-standard u_int{8,16,32,64}_t. + +This changes the types in the public headers and removes the u_int*_t +defines. This may break things. However, indentifiers ending with _t are +reserved by POSIX[1]; defining those can lead to undefined behavior. + +So if you rely on alsa-lib defining those for you, then you want the +compiler to error so things can be fixed properly. + +[1]: http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_02_02 + +Signed-off-by: Natanael Copa +Signed-off-by: Takashi Iwai +--- + include/pcm.h | 10 ++- + include/type_compat.h | 12 --- + src/pcm/interval.c | 4 +- + src/pcm/mask_inline.h | 6 +- + src/pcm/pcm.c | 26 +++---- + src/pcm/pcm_iec958.c | 12 +-- + src/pcm/pcm_linear.c | 2 +- + src/pcm/pcm_misc.c | 42 +++++------ + src/pcm/pcm_rate_linear.c | 4 +- + src/pcm/pcm_route.c | 2 +- + src/pcm/plugin_ops.h | 182 +++++++++++++++++++++++----------------------- + 11 files changed, 146 insertions(+), 156 deletions(-) + +diff --git a/include/pcm.h b/include/pcm.h +index 0be1a321..d44de54b 100644 +--- a/include/pcm.h ++++ b/include/pcm.h +@@ -33,6 +33,8 @@ + extern "C" { + #endif + ++#include ++ + /** + * \defgroup PCM PCM Interface + * See the \ref pcm page for more details. +@@ -1108,10 +1110,10 @@ int snd_pcm_format_width(snd_pcm_format_t format); /* in bits */ + int snd_pcm_format_physical_width(snd_pcm_format_t format); /* in bits */ + snd_pcm_format_t snd_pcm_build_linear_format(int width, int pwidth, int unsignd, int big_endian); + ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples); +-u_int8_t snd_pcm_format_silence(snd_pcm_format_t format); +-u_int16_t snd_pcm_format_silence_16(snd_pcm_format_t format); +-u_int32_t snd_pcm_format_silence_32(snd_pcm_format_t format); +-u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format); ++uint8_t snd_pcm_format_silence(snd_pcm_format_t format); ++uint16_t snd_pcm_format_silence_16(snd_pcm_format_t format); ++uint32_t snd_pcm_format_silence_32(snd_pcm_format_t format); ++uint64_t snd_pcm_format_silence_64(snd_pcm_format_t format); + int snd_pcm_format_set_silence(snd_pcm_format_t format, void *buf, unsigned int samples); + + snd_pcm_sframes_t snd_pcm_bytes_to_frames(snd_pcm_t *pcm, ssize_t bytes); +diff --git a/include/type_compat.h b/include/type_compat.h +index 0c10aed7..35973b1e 100644 +--- a/include/type_compat.h ++++ b/include/type_compat.h +@@ -47,18 +47,6 @@ + #ifndef __le64 + #define __le64 uint64_t + #endif +-#ifndef u_int8_t +-#define u_int8_t uint8_t +-#endif +-#ifndef u_int16_t +-#define u_int16_t uint16_t +-#endif +-#ifndef u_int32_t +-#define u_int32_t uint32_t +-#endif +-#ifndef u_int32_t +-#define u_int32_t uint64_t +-#endif + #ifndef __kernel_pid_t + #define __kernel_pid_t pid_t + #endif +diff --git a/src/pcm/interval.c b/src/pcm/interval.c +index 6e398084..74ec3204 100644 +--- a/src/pcm/interval.c ++++ b/src/pcm/interval.c +@@ -26,7 +26,7 @@ + #include + #include "pcm_local.h" + +-static inline void div64_32(u_int64_t *n, u_int32_t d, u_int32_t *rem) ++static inline void div64_32(uint64_t *n, uint32_t d, uint32_t *rem) + { + *rem = *n % d; + *n /= d; +@@ -88,7 +88,7 @@ static inline unsigned int sub(unsigned int a, unsigned int b) + static inline unsigned int muldiv32(unsigned int a, unsigned int b, + unsigned int c, unsigned int *r) + { +- u_int64_t n = (u_int64_t) a * b; ++ uint64_t n = (uint64_t) a * b; + if (c == 0) { + assert(n > 0); + *r = 0; +diff --git a/src/pcm/mask_inline.h b/src/pcm/mask_inline.h +index f656568d..04c7ee6e 100644 +--- a/src/pcm/mask_inline.h ++++ b/src/pcm/mask_inline.h +@@ -29,7 +29,7 @@ + #define MASK_OFS(i) ((i) >> 5) + #define MASK_BIT(i) (1U << ((i) & 31)) + +-MASK_INLINE unsigned int ld2(u_int32_t v) ++MASK_INLINE unsigned int ld2(uint32_t v) + { + unsigned r = 0; + +@@ -54,7 +54,7 @@ MASK_INLINE unsigned int ld2(u_int32_t v) + return r; + } + +-MASK_INLINE unsigned int hweight32(u_int32_t v) ++MASK_INLINE unsigned int hweight32(uint32_t v) + { + v = (v & 0x55555555) + ((v >> 1) & 0x55555555); + v = (v & 0x33333333) + ((v >> 2) & 0x33333333); +@@ -75,7 +75,7 @@ MASK_INLINE void snd_mask_none(snd_mask_t *mask) + + MASK_INLINE void snd_mask_any(snd_mask_t *mask) + { +- memset(mask, 0xff, MASK_SIZE * sizeof(u_int32_t)); ++ memset(mask, 0xff, MASK_SIZE * sizeof(uint32_t)); + } + + MASK_INLINE int snd_mask_empty(const snd_mask_t *mask) +diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c +index 2b4ce8ec..fc7bd52c 100644 +--- a/src/pcm/pcm.c ++++ b/src/pcm/pcm.c +@@ -2894,7 +2894,7 @@ int snd_pcm_area_silence(const snd_pcm_channel_area_t *dst_area, snd_pcm_uframes + char *dst; + unsigned int dst_step; + int width; +- u_int64_t silence; ++ uint64_t silence; + if (!dst_area->addr) + return 0; + dst = snd_pcm_channel_area_addr(dst_area, dst_offset); +@@ -2902,7 +2902,7 @@ int snd_pcm_area_silence(const snd_pcm_channel_area_t *dst_area, snd_pcm_uframes + silence = snd_pcm_format_silence_64(format); + if (dst_area->step == (unsigned int) width) { + unsigned int dwords = samples * width / 64; +- u_int64_t *dstp = (u_int64_t *)dst; ++ uint64_t *dstp = (uint64_t *)dst; + samples -= dwords * 64 / width; + while (dwords-- > 0) + *dstp++ = silence; +@@ -2912,8 +2912,8 @@ int snd_pcm_area_silence(const snd_pcm_channel_area_t *dst_area, snd_pcm_uframes + dst_step = dst_area->step / 8; + switch (width) { + case 4: { +- u_int8_t s0 = silence & 0xf0; +- u_int8_t s1 = silence & 0x0f; ++ uint8_t s0 = silence & 0xf0; ++ uint8_t s1 = silence & 0x0f; + int dstbit = dst_area->first % 8; + int dstbit_step = dst_area->step % 8; + while (samples-- > 0) { +@@ -2934,7 +2934,7 @@ int snd_pcm_area_silence(const snd_pcm_channel_area_t *dst_area, snd_pcm_uframes + break; + } + case 8: { +- u_int8_t sil = silence; ++ uint8_t sil = silence; + while (samples-- > 0) { + *dst = sil; + dst += dst_step; +@@ -2942,9 +2942,9 @@ int snd_pcm_area_silence(const snd_pcm_channel_area_t *dst_area, snd_pcm_uframes + break; + } + case 16: { +- u_int16_t sil = silence; ++ uint16_t sil = silence; + while (samples-- > 0) { +- *(u_int16_t*)dst = sil; ++ *(uint16_t*)dst = sil; + dst += dst_step; + } + break; +@@ -2961,16 +2961,16 @@ int snd_pcm_area_silence(const snd_pcm_channel_area_t *dst_area, snd_pcm_uframes + #endif + break; + case 32: { +- u_int32_t sil = silence; ++ uint32_t sil = silence; + while (samples-- > 0) { +- *(u_int32_t*)dst = sil; ++ *(uint32_t*)dst = sil; + dst += dst_step; + } + break; + } + case 64: { + while (samples-- > 0) { +- *(u_int64_t*)dst = silence; ++ *(uint64_t*)dst = silence; + dst += dst_step; + } + break; +@@ -3114,7 +3114,7 @@ int snd_pcm_area_copy(const snd_pcm_channel_area_t *dst_area, snd_pcm_uframes_t + } + case 16: { + while (samples-- > 0) { +- *(u_int16_t*)dst = *(const u_int16_t*)src; ++ *(uint16_t*)dst = *(const uint16_t*)src; + src += src_step; + dst += dst_step; + } +@@ -3131,7 +3131,7 @@ int snd_pcm_area_copy(const snd_pcm_channel_area_t *dst_area, snd_pcm_uframes_t + break; + case 32: { + while (samples-- > 0) { +- *(u_int32_t*)dst = *(const u_int32_t*)src; ++ *(uint32_t*)dst = *(const uint32_t*)src; + src += src_step; + dst += dst_step; + } +@@ -3139,7 +3139,7 @@ int snd_pcm_area_copy(const snd_pcm_channel_area_t *dst_area, snd_pcm_uframes_t + } + case 64: { + while (samples-- > 0) { +- *(u_int64_t*)dst = *(const u_int64_t*)src; ++ *(uint64_t*)dst = *(const uint64_t*)src; + src += src_step; + dst += dst_step; + } +diff --git a/src/pcm/pcm_iec958.c b/src/pcm/pcm_iec958.c +index 86ac9cfd..115092de 100644 +--- a/src/pcm/pcm_iec958.c ++++ b/src/pcm/pcm_iec958.c +@@ -102,7 +102,7 @@ static unsigned int iec958_parity(unsigned int data) + * 31 = parity + */ + +-static inline u_int32_t iec958_subframe(snd_pcm_iec958_t *iec, u_int32_t data, int channel) ++static inline uint32_t iec958_subframe(snd_pcm_iec958_t *iec, uint32_t data, int channel) + { + unsigned int byte = iec->counter >> 3; + unsigned int mask = 1 << (iec->counter - (byte << 3)); +@@ -132,7 +132,7 @@ static inline u_int32_t iec958_subframe(snd_pcm_iec958_t *iec, u_int32_t data, i + return data; + } + +-static inline int32_t iec958_to_s32(snd_pcm_iec958_t *iec, u_int32_t data) ++static inline int32_t iec958_to_s32(snd_pcm_iec958_t *iec, uint32_t data) + { + if (iec->byteswap) + data = bswap_32(data); +@@ -155,7 +155,7 @@ static void snd_pcm_iec958_decode(snd_pcm_iec958_t *iec, + void *put = put32_labels[iec->getput_idx]; + unsigned int channel; + for (channel = 0; channel < channels; ++channel) { +- const u_int32_t *src; ++ const uint32_t *src; + char *dst; + int src_step, dst_step; + snd_pcm_uframes_t frames1; +@@ -163,7 +163,7 @@ static void snd_pcm_iec958_decode(snd_pcm_iec958_t *iec, + const snd_pcm_channel_area_t *dst_area = &dst_areas[channel]; + src = snd_pcm_channel_area_addr(src_area, src_offset); + dst = snd_pcm_channel_area_addr(dst_area, dst_offset); +- src_step = snd_pcm_channel_area_step(src_area) / sizeof(u_int32_t); ++ src_step = snd_pcm_channel_area_step(src_area) / sizeof(uint32_t); + dst_step = snd_pcm_channel_area_step(dst_area); + frames1 = frames; + while (frames1-- > 0) { +@@ -195,7 +195,7 @@ static void snd_pcm_iec958_encode(snd_pcm_iec958_t *iec, + int counter = iec->counter; + for (channel = 0; channel < channels; ++channel) { + const char *src; +- u_int32_t *dst; ++ uint32_t *dst; + int src_step, dst_step; + snd_pcm_uframes_t frames1; + const snd_pcm_channel_area_t *src_area = &src_areas[channel]; +@@ -203,7 +203,7 @@ static void snd_pcm_iec958_encode(snd_pcm_iec958_t *iec, + src = snd_pcm_channel_area_addr(src_area, src_offset); + dst = snd_pcm_channel_area_addr(dst_area, dst_offset); + src_step = snd_pcm_channel_area_step(src_area); +- dst_step = snd_pcm_channel_area_step(dst_area) / sizeof(u_int32_t); ++ dst_step = snd_pcm_channel_area_step(dst_area) / sizeof(uint32_t); + frames1 = frames; + iec->counter = counter; + while (frames1-- > 0) { +diff --git a/src/pcm/pcm_linear.c b/src/pcm/pcm_linear.c +index 50df7794..9b1d9638 100644 +--- a/src/pcm/pcm_linear.c ++++ b/src/pcm/pcm_linear.c +@@ -183,7 +183,7 @@ void snd_pcm_linear_getput(const snd_pcm_channel_area_t *dst_areas, snd_pcm_ufra + void *get = get32_labels[get_idx]; + void *put = put32_labels[put_idx]; + unsigned int channel; +- u_int32_t sample = 0; ++ uint32_t sample = 0; + for (channel = 0; channel < channels; ++channel) { + const char *src; + char *dst; +diff --git a/src/pcm/pcm_misc.c b/src/pcm/pcm_misc.c +index 7d2b05db..a321c87e 100644 +--- a/src/pcm/pcm_misc.c ++++ b/src/pcm/pcm_misc.c +@@ -387,7 +387,7 @@ ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples) + * \param format Sample format + * \return silence 64 bit word + */ +-u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format) ++uint64_t snd_pcm_format_silence_64(snd_pcm_format_t format) + { + switch (format) { + case SNDRV_PCM_FORMAT_S8: +@@ -467,7 +467,7 @@ u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format) + { + union { + float f[2]; +- u_int64_t i; ++ uint64_t i; + } u; + u.f[0] = u.f[1] = 0.0; + #ifdef SNDRV_LITTLE_ENDIAN +@@ -480,7 +480,7 @@ u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format) + { + union { + double f; +- u_int64_t i; ++ uint64_t i; + } u; + u.f = 0.0; + #ifdef SNDRV_LITTLE_ENDIAN +@@ -493,7 +493,7 @@ u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format) + { + union { + float f[2]; +- u_int64_t i; ++ uint64_t i; + } u; + u.f[0] = u.f[1] = 0.0; + #ifdef SNDRV_LITTLE_ENDIAN +@@ -506,7 +506,7 @@ u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format) + { + union { + double f; +- u_int64_t i; ++ uint64_t i; + } u; + u.f = 0.0; + #ifdef SNDRV_LITTLE_ENDIAN +@@ -539,10 +539,10 @@ u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format) + * \param format Sample format + * \return silence 32 bit word + */ +-u_int32_t snd_pcm_format_silence_32(snd_pcm_format_t format) ++uint32_t snd_pcm_format_silence_32(snd_pcm_format_t format) + { + assert(snd_pcm_format_physical_width(format) <= 32); +- return (u_int32_t)snd_pcm_format_silence_64(format); ++ return (uint32_t)snd_pcm_format_silence_64(format); + } + + /** +@@ -550,10 +550,10 @@ u_int32_t snd_pcm_format_silence_32(snd_pcm_format_t format) + * \param format Sample format + * \return silence 16 bit word + */ +-u_int16_t snd_pcm_format_silence_16(snd_pcm_format_t format) ++uint16_t snd_pcm_format_silence_16(snd_pcm_format_t format) + { + assert(snd_pcm_format_physical_width(format) <= 16); +- return (u_int16_t)snd_pcm_format_silence_64(format); ++ return (uint16_t)snd_pcm_format_silence_64(format); + } + + /** +@@ -561,10 +561,10 @@ u_int16_t snd_pcm_format_silence_16(snd_pcm_format_t format) + * \param format Sample format + * \return silence 8 bit word + */ +-u_int8_t snd_pcm_format_silence(snd_pcm_format_t format) ++uint8_t snd_pcm_format_silence(snd_pcm_format_t format) + { + assert(snd_pcm_format_physical_width(format) <= 8); +- return (u_int8_t)snd_pcm_format_silence_64(format); ++ return (uint8_t)snd_pcm_format_silence_64(format); + } + + /** +@@ -580,7 +580,7 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int + return 0; + switch (snd_pcm_format_physical_width(format)) { + case 4: { +- u_int8_t silence = snd_pcm_format_silence_64(format); ++ uint8_t silence = snd_pcm_format_silence_64(format); + unsigned int samples1; + if (samples % 2 != 0) + return -EINVAL; +@@ -589,13 +589,13 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int + break; + } + case 8: { +- u_int8_t silence = snd_pcm_format_silence_64(format); ++ uint8_t silence = snd_pcm_format_silence_64(format); + memset(data, silence, samples); + break; + } + case 16: { +- u_int16_t silence = snd_pcm_format_silence_64(format); +- u_int16_t *pdata = (u_int16_t *)data; ++ uint16_t silence = snd_pcm_format_silence_64(format); ++ uint16_t *pdata = (uint16_t *)data; + if (! silence) + memset(data, 0, samples * 2); + else { +@@ -605,8 +605,8 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int + break; + } + case 24: { +- u_int32_t silence = snd_pcm_format_silence_64(format); +- u_int8_t *pdata = (u_int8_t *)data; ++ uint32_t silence = snd_pcm_format_silence_64(format); ++ uint8_t *pdata = (uint8_t *)data; + if (! silence) + memset(data, 0, samples * 3); + else { +@@ -625,8 +625,8 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int + break; + } + case 32: { +- u_int32_t silence = snd_pcm_format_silence_64(format); +- u_int32_t *pdata = (u_int32_t *)data; ++ uint32_t silence = snd_pcm_format_silence_64(format); ++ uint32_t *pdata = (uint32_t *)data; + if (! silence) + memset(data, 0, samples * 4); + else { +@@ -636,8 +636,8 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int + break; + } + case 64: { +- u_int64_t silence = snd_pcm_format_silence_64(format); +- u_int64_t *pdata = (u_int64_t *)data; ++ uint64_t silence = snd_pcm_format_silence_64(format); ++ uint64_t *pdata = (uint64_t *)data; + if (! silence) + memset(data, 0, samples * 8); + else { +diff --git a/src/pcm/pcm_rate_linear.c b/src/pcm/pcm_rate_linear.c +index 70399e0d..b20c715a 100644 +--- a/src/pcm/pcm_rate_linear.c ++++ b/src/pcm/pcm_rate_linear.c +@@ -346,7 +346,7 @@ static int linear_init(void *obj, snd_pcm_rate_info_t *info) + rate->func = linear_shrink; + /* pitch is get_increment */ + } +- rate->pitch = (((u_int64_t)info->out.rate * LINEAR_DIV) + ++ rate->pitch = (((uint64_t)info->out.rate * LINEAR_DIV) + + (info->in.rate / 2)) / info->in.rate; + rate->channels = info->channels; + +@@ -363,7 +363,7 @@ static int linear_adjust_pitch(void *obj, snd_pcm_rate_info_t *info) + struct rate_linear *rate = obj; + snd_pcm_uframes_t cframes; + +- rate->pitch = (((u_int64_t)info->out.period_size * LINEAR_DIV) + ++ rate->pitch = (((uint64_t)info->out.period_size * LINEAR_DIV) + + (info->in.period_size/2) ) / info->in.period_size; + + cframes = input_frames(rate, info->out.period_size); +diff --git a/src/pcm/pcm_route.c b/src/pcm/pcm_route.c +index 508d5b0f..1bb83d2f 100644 +--- a/src/pcm/pcm_route.c ++++ b/src/pcm/pcm_route.c +@@ -190,7 +190,7 @@ static void snd_pcm_route_convert1_one_getput(const snd_pcm_channel_area_t *dst_ + const char *src; + char *dst; + int src_step, dst_step; +- u_int32_t sample = 0; ++ uint32_t sample = 0; + for (srcidx = 0; srcidx < ttable->nsrcs && srcidx < src_channels; ++srcidx) { + unsigned int channel = ttable->srcs[srcidx].channel; + if (channel >= src_channels) +diff --git a/src/pcm/plugin_ops.h b/src/pcm/plugin_ops.h +index eb8c2c4f..69e7f2cf 100644 +--- a/src/pcm/plugin_ops.h ++++ b/src/pcm/plugin_ops.h +@@ -21,13 +21,13 @@ + + #ifndef SX_INLINES + #define SX_INLINES +-static inline u_int32_t sx24(u_int32_t x) ++static inline uint32_t sx24(uint32_t x) + { + if(x&0x00800000) + return x|0xFF000000; + return x&0x00FFFFFF; + } +-static inline u_int32_t sx24s(u_int32_t x) ++static inline uint32_t sx24s(uint32_t x) + { + if(x&0x00008000) + return x|0x000000FF; +@@ -35,10 +35,10 @@ static inline u_int32_t sx24s(u_int32_t x) + } + #endif + +-#define as_u8(ptr) (*(u_int8_t*)(ptr)) +-#define as_u16(ptr) (*(u_int16_t*)(ptr)) +-#define as_u32(ptr) (*(u_int32_t*)(ptr)) +-#define as_u64(ptr) (*(u_int64_t*)(ptr)) ++#define as_u8(ptr) (*(uint8_t*)(ptr)) ++#define as_u16(ptr) (*(uint16_t*)(ptr)) ++#define as_u32(ptr) (*(uint32_t*)(ptr)) ++#define as_u64(ptr) (*(uint64_t*)(ptr)) + #define as_s8(ptr) (*(int8_t*)(ptr)) + #define as_s16(ptr) (*(int16_t*)(ptr)) + #define as_s32(ptr) (*(int32_t*)(ptr)) +@@ -46,10 +46,10 @@ static inline u_int32_t sx24s(u_int32_t x) + #define as_float(ptr) (*(float_t*)(ptr)) + #define as_double(ptr) (*(double_t*)(ptr)) + +-#define as_u8c(ptr) (*(const u_int8_t*)(ptr)) +-#define as_u16c(ptr) (*(const u_int16_t*)(ptr)) +-#define as_u32c(ptr) (*(const u_int32_t*)(ptr)) +-#define as_u64c(ptr) (*(const u_int64_t*)(ptr)) ++#define as_u8c(ptr) (*(const uint8_t*)(ptr)) ++#define as_u16c(ptr) (*(const uint16_t*)(ptr)) ++#define as_u32c(ptr) (*(const uint32_t*)(ptr)) ++#define as_u64c(ptr) (*(const uint64_t*)(ptr)) + #define as_s8c(ptr) (*(const int8_t*)(ptr)) + #define as_s16c(ptr) (*(const int16_t*)(ptr)) + #define as_s32c(ptr) (*(const int32_t*)(ptr)) +@@ -57,18 +57,18 @@ static inline u_int32_t sx24s(u_int32_t x) + #define as_floatc(ptr) (*(const float_t*)(ptr)) + #define as_doublec(ptr) (*(const double_t*)(ptr)) + +-#define _get_triple_le(ptr) (*(u_int8_t*)(ptr) | (u_int32_t)*((u_int8_t*)(ptr) + 1) << 8 | (u_int32_t)*((u_int8_t*)(ptr) + 2) << 16) +-#define _get_triple_be(ptr) ((u_int32_t)*(u_int8_t*)(ptr) << 16 | (u_int32_t)*((u_int8_t*)(ptr) + 1) << 8 | *((u_int8_t*)(ptr) + 2)) ++#define _get_triple_le(ptr) (*(uint8_t*)(ptr) | (uint32_t)*((uint8_t*)(ptr) + 1) << 8 | (uint32_t)*((uint8_t*)(ptr) + 2) << 16) ++#define _get_triple_be(ptr) ((uint32_t)*(uint8_t*)(ptr) << 16 | (uint32_t)*((uint8_t*)(ptr) + 1) << 8 | *((uint8_t*)(ptr) + 2)) + #define _put_triple_le(ptr,val) do { \ +- u_int8_t *_tmp = (u_int8_t *)(ptr); \ +- u_int32_t _val = (val); \ ++ uint8_t *_tmp = (uint8_t *)(ptr); \ ++ uint32_t _val = (val); \ + _tmp[0] = _val; \ + _tmp[1] = _val >> 8; \ + _tmp[2] = _val >> 16; \ + } while(0) + #define _put_triple_be(ptr,val) do { \ +- u_int8_t *_tmp = (u_int8_t *)(ptr); \ +- u_int32_t _val = (val); \ ++ uint8_t *_tmp = (uint8_t *)(ptr); \ ++ uint32_t _val = (val); \ + _tmp[0] = _val >> 16; \ + _tmp[1] = _val >> 8; \ + _tmp[2] = _val; \ +@@ -243,45 +243,45 @@ static void *const conv_labels[4 * 2 * 2 * 4 * 2] = { + #ifdef CONV_END + while(0) { + conv_xxx1_xxx1: as_u8(dst) = as_u8c(src); goto CONV_END; +-conv_xxx1_xx10: as_u16(dst) = (u_int16_t)as_u8c(src) << 8; goto CONV_END; +-conv_xxx1_xx01: as_u16(dst) = (u_int16_t)as_u8c(src); goto CONV_END; +-conv_xxx1_x100: as_u32(dst) = sx24((u_int32_t)as_u8c(src) << 16); goto CONV_END; +-conv_xxx1_001x: as_u32(dst) = sx24s((u_int32_t)as_u8c(src) << 8); goto CONV_END; +-conv_xxx1_1000: as_u32(dst) = (u_int32_t)as_u8c(src) << 24; goto CONV_END; +-conv_xxx1_0001: as_u32(dst) = (u_int32_t)as_u8c(src); goto CONV_END; ++conv_xxx1_xx10: as_u16(dst) = (uint16_t)as_u8c(src) << 8; goto CONV_END; ++conv_xxx1_xx01: as_u16(dst) = (uint16_t)as_u8c(src); goto CONV_END; ++conv_xxx1_x100: as_u32(dst) = sx24((uint32_t)as_u8c(src) << 16); goto CONV_END; ++conv_xxx1_001x: as_u32(dst) = sx24s((uint32_t)as_u8c(src) << 8); goto CONV_END; ++conv_xxx1_1000: as_u32(dst) = (uint32_t)as_u8c(src) << 24; goto CONV_END; ++conv_xxx1_0001: as_u32(dst) = (uint32_t)as_u8c(src); goto CONV_END; + conv_xxx1_xxx9: as_u8(dst) = as_u8c(src) ^ 0x80; goto CONV_END; +-conv_xxx1_xx90: as_u16(dst) = (u_int16_t)(as_u8c(src) ^ 0x80) << 8; goto CONV_END; +-conv_xxx1_xx09: as_u16(dst) = (u_int16_t)(as_u8c(src) ^ 0x80); goto CONV_END; +-conv_xxx1_x900: as_u32(dst) = sx24((u_int32_t)(as_u8c(src) ^ 0x80) << 16); goto CONV_END; +-conv_xxx1_009x: as_u32(dst) = sx24s((u_int32_t)(as_u8c(src) ^ 0x80) << 8); goto CONV_END; +-conv_xxx1_9000: as_u32(dst) = (u_int32_t)(as_u8c(src) ^ 0x80) << 24; goto CONV_END; +-conv_xxx1_0009: as_u32(dst) = (u_int32_t)(as_u8c(src) ^ 0x80); goto CONV_END; ++conv_xxx1_xx90: as_u16(dst) = (uint16_t)(as_u8c(src) ^ 0x80) << 8; goto CONV_END; ++conv_xxx1_xx09: as_u16(dst) = (uint16_t)(as_u8c(src) ^ 0x80); goto CONV_END; ++conv_xxx1_x900: as_u32(dst) = sx24((uint32_t)(as_u8c(src) ^ 0x80) << 16); goto CONV_END; ++conv_xxx1_009x: as_u32(dst) = sx24s((uint32_t)(as_u8c(src) ^ 0x80) << 8); goto CONV_END; ++conv_xxx1_9000: as_u32(dst) = (uint32_t)(as_u8c(src) ^ 0x80) << 24; goto CONV_END; ++conv_xxx1_0009: as_u32(dst) = (uint32_t)(as_u8c(src) ^ 0x80); goto CONV_END; + conv_xx12_xxx1: as_u8(dst) = as_u16c(src) >> 8; goto CONV_END; + conv_xx12_xx12: as_u16(dst) = as_u16c(src); goto CONV_END; + conv_xx12_xx21: as_u16(dst) = bswap_16(as_u16c(src)); goto CONV_END; +-conv_xx12_x120: as_u32(dst) = sx24((u_int32_t)as_u16c(src) << 8); goto CONV_END; +-conv_xx12_021x: as_u32(dst) = sx24s((u_int32_t)bswap_16(as_u16c(src)) << 8); goto CONV_END; +-conv_xx12_1200: as_u32(dst) = (u_int32_t)as_u16c(src) << 16; goto CONV_END; +-conv_xx12_0021: as_u32(dst) = (u_int32_t)bswap_16(as_u16c(src)); goto CONV_END; ++conv_xx12_x120: as_u32(dst) = sx24((uint32_t)as_u16c(src) << 8); goto CONV_END; ++conv_xx12_021x: as_u32(dst) = sx24s((uint32_t)bswap_16(as_u16c(src)) << 8); goto CONV_END; ++conv_xx12_1200: as_u32(dst) = (uint32_t)as_u16c(src) << 16; goto CONV_END; ++conv_xx12_0021: as_u32(dst) = (uint32_t)bswap_16(as_u16c(src)); goto CONV_END; + conv_xx12_xxx9: as_u8(dst) = (as_u16c(src) >> 8) ^ 0x80; goto CONV_END; + conv_xx12_xx92: as_u16(dst) = as_u16c(src) ^ 0x8000; goto CONV_END; + conv_xx12_xx29: as_u16(dst) = bswap_16(as_u16c(src)) ^ 0x80; goto CONV_END; +-conv_xx12_x920: as_u32(dst) = sx24((u_int32_t)(as_u16c(src) ^ 0x8000) << 8); goto CONV_END; +-conv_xx12_029x: as_u32(dst) = sx24s((u_int32_t)(bswap_16(as_u16c(src)) ^ 0x80) << 8); goto CONV_END; +-conv_xx12_9200: as_u32(dst) = (u_int32_t)(as_u16c(src) ^ 0x8000) << 16; goto CONV_END; +-conv_xx12_0029: as_u32(dst) = (u_int32_t)(bswap_16(as_u16c(src)) ^ 0x80); goto CONV_END; ++conv_xx12_x920: as_u32(dst) = sx24((uint32_t)(as_u16c(src) ^ 0x8000) << 8); goto CONV_END; ++conv_xx12_029x: as_u32(dst) = sx24s((uint32_t)(bswap_16(as_u16c(src)) ^ 0x80) << 8); goto CONV_END; ++conv_xx12_9200: as_u32(dst) = (uint32_t)(as_u16c(src) ^ 0x8000) << 16; goto CONV_END; ++conv_xx12_0029: as_u32(dst) = (uint32_t)(bswap_16(as_u16c(src)) ^ 0x80); goto CONV_END; + conv_xx12_xxx2: as_u8(dst) = as_u16c(src) & 0xff; goto CONV_END; +-conv_xx12_x210: as_u32(dst) = sx24((u_int32_t)bswap_16(as_u16c(src)) << 8); goto CONV_END; +-conv_xx12_012x: as_u32(dst) = sx24s((u_int32_t)as_u16c(src) << 8); goto CONV_END; +-conv_xx12_2100: as_u32(dst) = (u_int32_t)bswap_16(as_u16c(src)) << 16; goto CONV_END; +-conv_xx12_0012: as_u32(dst) = (u_int32_t)as_u16c(src); goto CONV_END; ++conv_xx12_x210: as_u32(dst) = sx24((uint32_t)bswap_16(as_u16c(src)) << 8); goto CONV_END; ++conv_xx12_012x: as_u32(dst) = sx24s((uint32_t)as_u16c(src) << 8); goto CONV_END; ++conv_xx12_2100: as_u32(dst) = (uint32_t)bswap_16(as_u16c(src)) << 16; goto CONV_END; ++conv_xx12_0012: as_u32(dst) = (uint32_t)as_u16c(src); goto CONV_END; + conv_xx12_xxxA: as_u8(dst) = (as_u16c(src) ^ 0x80) & 0xff; goto CONV_END; + conv_xx12_xxA1: as_u16(dst) = bswap_16(as_u16c(src) ^ 0x80); goto CONV_END; + conv_xx12_xx1A: as_u16(dst) = as_u16c(src) ^ 0x80; goto CONV_END; +-conv_xx12_xA10: as_u32(dst) = sx24((u_int32_t)bswap_16(as_u16c(src) ^ 0x80) << 8); goto CONV_END; +-conv_xx12_01Ax: as_u32(dst) = sx24s((u_int32_t)(as_u16c(src) ^ 0x80) << 8); goto CONV_END; +-conv_xx12_A100: as_u32(dst) = (u_int32_t)bswap_16(as_u16c(src) ^ 0x80) << 16; goto CONV_END; +-conv_xx12_001A: as_u32(dst) = (u_int32_t)(as_u16c(src) ^ 0x80); goto CONV_END; ++conv_xx12_xA10: as_u32(dst) = sx24((uint32_t)bswap_16(as_u16c(src) ^ 0x80) << 8); goto CONV_END; ++conv_xx12_01Ax: as_u32(dst) = sx24s((uint32_t)(as_u16c(src) ^ 0x80) << 8); goto CONV_END; ++conv_xx12_A100: as_u32(dst) = (uint32_t)bswap_16(as_u16c(src) ^ 0x80) << 16; goto CONV_END; ++conv_xx12_001A: as_u32(dst) = (uint32_t)(as_u16c(src) ^ 0x80); goto CONV_END; + conv_x123_xxx1: as_u8(dst) = as_u32c(src) >> 16; goto CONV_END; + conv_x123_xx12: as_u16(dst) = as_u32c(src) >> 8; goto CONV_END; + conv_x123_xx21: as_u16(dst) = bswap_16(as_u32c(src) >> 8); goto CONV_END; +@@ -376,8 +376,8 @@ static void *const get16_labels[4 * 2 * 2 + 4 * 3] = { + + #ifdef GET16_END + while(0) { +-get16_1_10: sample = (u_int16_t)as_u8c(src) << 8; goto GET16_END; +-get16_1_90: sample = (u_int16_t)(as_u8c(src) ^ 0x80) << 8; goto GET16_END; ++get16_1_10: sample = (uint16_t)as_u8c(src) << 8; goto GET16_END; ++get16_1_90: sample = (uint16_t)(as_u8c(src) ^ 0x80) << 8; goto GET16_END; + get16_12_12: sample = as_u16c(src); goto GET16_END; + get16_12_92: sample = as_u16c(src) ^ 0x8000; goto GET16_END; + get16_12_21: sample = bswap_16(as_u16c(src)); goto GET16_END; +@@ -448,26 +448,26 @@ put16_12_12: as_u16(dst) = sample; goto PUT16_END; + put16_12_92: as_u16(dst) = sample ^ 0x8000; goto PUT16_END; + put16_12_21: as_u16(dst) = bswap_16(sample); goto PUT16_END; + put16_12_29: as_u16(dst) = bswap_16(sample) ^ 0x80; goto PUT16_END; +-put16_12_0120: as_u32(dst) = sx24((u_int32_t)sample << 8); goto PUT16_END; +-put16_12_0920: as_u32(dst) = sx24((u_int32_t)(sample ^ 0x8000) << 8); goto PUT16_END; +-put16_12_0210: as_u32(dst) = sx24s((u_int32_t)bswap_16(sample) << 8); goto PUT16_END; +-put16_12_0290: as_u32(dst) = sx24s((u_int32_t)(bswap_16(sample) ^ 0x80) << 8); goto PUT16_END; +-put16_12_1200: as_u32(dst) = (u_int32_t)sample << 16; goto PUT16_END; +-put16_12_9200: as_u32(dst) = (u_int32_t)(sample ^ 0x8000) << 16; goto PUT16_END; +-put16_12_0021: as_u32(dst) = (u_int32_t)bswap_16(sample); goto PUT16_END; +-put16_12_0029: as_u32(dst) = (u_int32_t)bswap_16(sample) ^ 0x80; goto PUT16_END; +-put16_12_120: _put_triple(dst, (u_int32_t)sample << 8); goto PUT16_END; +-put16_12_920: _put_triple(dst, (u_int32_t)(sample ^ 0x8000) << 8); goto PUT16_END; +-put16_12_021: _put_triple_s(dst, (u_int32_t)sample << 8); goto PUT16_END; +-put16_12_029: _put_triple_s(dst, (u_int32_t)(sample ^ 0x8000) << 8); goto PUT16_END; +-put16_12_120_20: _put_triple(dst, (u_int32_t)sample << 4); goto PUT16_END; +-put16_12_920_20: _put_triple(dst, (u_int32_t)(sample ^ 0x8000) << 4); goto PUT16_END; +-put16_12_021_20: _put_triple_s(dst, (u_int32_t)sample << 4); goto PUT16_END; +-put16_12_029_20: _put_triple_s(dst, (u_int32_t)(sample ^ 0x8000) << 4); goto PUT16_END; +-put16_12_120_18: _put_triple(dst, (u_int32_t)sample << 2); goto PUT16_END; +-put16_12_920_18: _put_triple(dst, (u_int32_t)(sample ^ 0x8000) << 2); goto PUT16_END; +-put16_12_021_18: _put_triple_s(dst, (u_int32_t)sample << 2); goto PUT16_END; +-put16_12_029_18: _put_triple_s(dst, (u_int32_t)(sample ^ 0x8000) << 2); goto PUT16_END; ++put16_12_0120: as_u32(dst) = sx24((uint32_t)sample << 8); goto PUT16_END; ++put16_12_0920: as_u32(dst) = sx24((uint32_t)(sample ^ 0x8000) << 8); goto PUT16_END; ++put16_12_0210: as_u32(dst) = sx24s((uint32_t)bswap_16(sample) << 8); goto PUT16_END; ++put16_12_0290: as_u32(dst) = sx24s((uint32_t)(bswap_16(sample) ^ 0x80) << 8); goto PUT16_END; ++put16_12_1200: as_u32(dst) = (uint32_t)sample << 16; goto PUT16_END; ++put16_12_9200: as_u32(dst) = (uint32_t)(sample ^ 0x8000) << 16; goto PUT16_END; ++put16_12_0021: as_u32(dst) = (uint32_t)bswap_16(sample); goto PUT16_END; ++put16_12_0029: as_u32(dst) = (uint32_t)bswap_16(sample) ^ 0x80; goto PUT16_END; ++put16_12_120: _put_triple(dst, (uint32_t)sample << 8); goto PUT16_END; ++put16_12_920: _put_triple(dst, (uint32_t)(sample ^ 0x8000) << 8); goto PUT16_END; ++put16_12_021: _put_triple_s(dst, (uint32_t)sample << 8); goto PUT16_END; ++put16_12_029: _put_triple_s(dst, (uint32_t)(sample ^ 0x8000) << 8); goto PUT16_END; ++put16_12_120_20: _put_triple(dst, (uint32_t)sample << 4); goto PUT16_END; ++put16_12_920_20: _put_triple(dst, (uint32_t)(sample ^ 0x8000) << 4); goto PUT16_END; ++put16_12_021_20: _put_triple_s(dst, (uint32_t)sample << 4); goto PUT16_END; ++put16_12_029_20: _put_triple_s(dst, (uint32_t)(sample ^ 0x8000) << 4); goto PUT16_END; ++put16_12_120_18: _put_triple(dst, (uint32_t)sample << 2); goto PUT16_END; ++put16_12_920_18: _put_triple(dst, (uint32_t)(sample ^ 0x8000) << 2); goto PUT16_END; ++put16_12_021_18: _put_triple_s(dst, (uint32_t)sample << 2); goto PUT16_END; ++put16_12_029_18: _put_triple_s(dst, (uint32_t)(sample ^ 0x8000) << 2); goto PUT16_END; + } + #endif + +@@ -517,12 +517,12 @@ static void *const get32_labels[4 * 2 * 2 + 4 * 3] = { + + #ifdef GET32_END + while (0) { +-get32_1_1000: sample = (u_int32_t)as_u8c(src) << 24; goto GET32_END; +-get32_1_9000: sample = (u_int32_t)(as_u8c(src) ^ 0x80) << 24; goto GET32_END; +-get32_12_1200: sample = (u_int32_t)as_u16c(src) << 16; goto GET32_END; +-get32_12_9200: sample = (u_int32_t)(as_u16c(src) ^ 0x8000) << 16; goto GET32_END; +-get32_12_2100: sample = (u_int32_t)bswap_16(as_u16c(src)) << 16; goto GET32_END; +-get32_12_A100: sample = (u_int32_t)bswap_16(as_u16c(src) ^ 0x80) << 16; goto GET32_END; ++get32_1_1000: sample = (uint32_t)as_u8c(src) << 24; goto GET32_END; ++get32_1_9000: sample = (uint32_t)(as_u8c(src) ^ 0x80) << 24; goto GET32_END; ++get32_12_1200: sample = (uint32_t)as_u16c(src) << 16; goto GET32_END; ++get32_12_9200: sample = (uint32_t)(as_u16c(src) ^ 0x8000) << 16; goto GET32_END; ++get32_12_2100: sample = (uint32_t)bswap_16(as_u16c(src)) << 16; goto GET32_END; ++get32_12_A100: sample = (uint32_t)bswap_16(as_u16c(src) ^ 0x80) << 16; goto GET32_END; + get32_0123_1230: sample = as_u32c(src) << 8; goto GET32_END; + get32_0123_9230: sample = (as_u32c(src) << 8) ^ 0x80000000; goto GET32_END; + get32_1230_3210: sample = bswap_32(as_u32c(src) >> 8); goto GET32_END; +@@ -786,18 +786,18 @@ static inline void _norms(const void *src, void *dst, + s += (1U << (dst_wid - 1)); + switch (dst_wid) { + case 8: +- *(u_int8_t*)dst = s; ++ *(uint8_t*)dst = s; + break; + case 16: + if (dst_end) + s = bswap_16(s); +- *(u_int16_t*)dst = s; ++ *(uint16_t*)dst = s; + break; + case 24: + case 32: + if (dst_end) + s = bswap_32(s); +- *(u_int32_t*)dst = s; ++ *(uint32_t*)dst = s; + break; + } + return; +@@ -806,27 +806,27 @@ static inline void _norms(const void *src, void *dst, + switch (dst_wid) { + case 8: + if (dst_sign) +- *(u_int8_t*)dst = 0x80; ++ *(uint8_t*)dst = 0x80; + else +- *(u_int8_t*)dst = 0; ++ *(uint8_t*)dst = 0; + break; + case 16: + if (dst_sign) +- *(u_int16_t*)dst = dst_end ? 0x0080 : 0x8000; ++ *(uint16_t*)dst = dst_end ? 0x0080 : 0x8000; + else +- *(u_int16_t*)dst = 0; ++ *(uint16_t*)dst = 0; + break; + case 24: + if (dst_sign) +- *(u_int32_t*)dst = dst_end ? 0x00008000 : 0x00800000; ++ *(uint32_t*)dst = dst_end ? 0x00008000 : 0x00800000; + else +- *(u_int32_t*)dst = 0; ++ *(uint32_t*)dst = 0; + break; + case 32: + if (dst_sign) +- *(u_int32_t*)dst = dst_end ? 0x00000080 : 0x80000000; ++ *(uint32_t*)dst = dst_end ? 0x00000080 : 0x80000000; + else +- *(u_int32_t*)dst = 0; ++ *(uint32_t*)dst = 0; + break; + default: + assert(0); +@@ -838,27 +838,27 @@ static inline void _norms(const void *src, void *dst, + switch (dst_wid) { + case 8: + if (dst_sign) +- *(u_int8_t*)dst = 0x7f; ++ *(uint8_t*)dst = 0x7f; + else +- *(u_int8_t*)dst = 0xff; ++ *(uint8_t*)dst = 0xff; + break; + case 16: + if (dst_sign) +- *(u_int16_t*)dst = dst_end ? 0xff7f : 0x7fff; ++ *(uint16_t*)dst = dst_end ? 0xff7f : 0x7fff; + else +- *(u_int16_t*)dst = 0; ++ *(uint16_t*)dst = 0; + break; + case 24: + if (dst_sign) +- *(u_int32_t*)dst = dst_end ? 0xffff7f00 : 0x007fffff; ++ *(uint32_t*)dst = dst_end ? 0xffff7f00 : 0x007fffff; + else +- *(u_int32_t*)dst = 0; ++ *(uint32_t*)dst = 0; + break; + case 32: + if (dst_sign) +- *(u_int32_t*)dst = dst_end ? 0xffffff7f : 0x7fffffff; ++ *(uint32_t*)dst = dst_end ? 0xffffff7f : 0x7fffffff; + else +- *(u_int32_t*)dst = 0; ++ *(uint32_t*)dst = 0; + break; + default: + assert(0); +-- +2.13.5 + + +From cb34cee0d8da2fb131986d5782ddf5cec985c532 Mon Sep 17 00:00:00 2001 +From: Natanael Copa +Date: Fri, 14 Jul 2017 18:47:05 +0200 +Subject: [PATCH 28/39] snd_user_file: avoid use wordexp + +As suggested in POSIX[1], wordexp might execute the shell. If the libc +implementation does so, it will break the firefox sandbox which does +not allow exec. This happened on Alpine Linux with musl libc[2]. + +Since we cannot guarantee that the system wordexp implementation does +not execute shell, we cannot really use it, and need to implement the +~/ expansion ourselves. + +We provide a configure option --with-wordexp for users that still may +need it, but we leave this off by default because wordexp is a large +attack vector and it is better to avoid it. + +[1]: http://pubs.opengroup.org/onlinepubs/9699919799/functions/wordexp.html#tag_16_684_08 +[2]: http://bugs.alpinelinux.org/issues/7454#note-2 + +Signed-off-by: Natanael Copa +Signed-off-by: Takashi Iwai +--- + configure.ac | 19 ++++++++++++++++- + src/userfile.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- + 2 files changed, 75 insertions(+), 9 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 26e5d125..fbcfa829 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -303,8 +303,25 @@ fi + + AC_SUBST(ALSA_DEPLIBS) + ++dnl Check for use of wordexp... ++AC_MSG_CHECKING(for use of wordexp) ++AC_ARG_WITH(wordexp, ++ AS_HELP_STRING([--with-wordexp], ++ [Use wordexp when expanding configs (default = no)]), ++ [case "$withval" in ++ y|yes) wordexp=yes ;; ++ *) wordexp=no ;; ++ esac],) ++if test "$wordexp" = "yes" ; then ++ AC_DEFINE(HAVE_WORDEXP, "1", [Enable use of wordexp]) ++ AC_MSG_RESULT(yes) ++ AC_CHECK_HEADER([wordexp.h],[], [AC_MSG_ERROR([Couldn't find wordexp.h])]) ++else ++ AC_MSG_RESULT(no) ++fi ++ + dnl Check for headers +-AC_CHECK_HEADERS([wordexp.h endian.h sys/endian.h sys/shm.h]) ++AC_CHECK_HEADERS([endian.h sys/endian.h sys/shm.h]) + + dnl Check for resmgr support... + AC_MSG_CHECKING(for resmgr support) +diff --git a/src/userfile.c b/src/userfile.c +index 72779da4..f2145470 100644 +--- a/src/userfile.c ++++ b/src/userfile.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + /** + * \brief Get the full file name +@@ -32,14 +33,13 @@ + * stores the first matchine one. The returned string is strdup'ed. + */ + +-#ifdef HAVE_WORDEXP_H ++#ifdef HAVE_WORDEXP + #include +-#include + int snd_user_file(const char *file, char **result) + { + wordexp_t we; + int err; +- ++ + assert(file && result); + err = wordexp(file, &we, WRDE_NOCMD); + switch (err) { +@@ -61,13 +61,62 @@ int snd_user_file(const char *file, char **result) + return 0; + } + +-#else /* !HAVE_WORDEXP_H */ +-/* just copy the string - would be nicer to expand by ourselves, though... */ ++#else /* !HAVE_WORDEX */ ++ ++#include ++#include ++#include ++#include ++#include ++ + int snd_user_file(const char *file, char **result) + { +- *result = strdup(file); +- if (! *result) ++ int err; ++ size_t len; ++ char *buf = NULL; ++ ++ assert(file && result); ++ *result = NULL; ++ ++ /* expand ~/ if needed */ ++ if (file[0] == '~' && file[1] == '/') { ++ const char *home = getenv("HOME"); ++ if (home == NULL) { ++ struct passwd pwent, *p = NULL; ++ uid_t id = getuid(); ++ size_t bufsize = 1024; ++ ++ buf = malloc(bufsize); ++ if (buf == NULL) ++ goto out; ++ ++ while ((err = getpwuid_r(id, &pwent, buf, bufsize, &p)) == ERANGE) { ++ char *newbuf; ++ bufsize += 1024; ++ if (bufsize < 1024) ++ break; ++ newbuf = realloc(buf, bufsize); ++ if (newbuf == NULL) ++ goto out; ++ buf = newbuf; ++ } ++ home = err ? "" : pwent.pw_dir; ++ } ++ len = strlen(home) + strlen(&file[2]) + 2; ++ *result = malloc(len); ++ if (*result) ++ snprintf(*result, len, "%s/%s", home, &file[2]); ++ } else { ++ *result = strdup(file); ++ } ++ ++out: ++ if (buf) ++ free(buf); ++ ++ if (*result == NULL) + return -ENOMEM; + return 0; + } +-#endif /* HAVE_WORDEXP_H */ ++ ++#endif /* HAVE_WORDEXP */ +-- +2.13.5 + + +From c01dc3fa4899a9b9948629c103c0bc435d4f1574 Mon Sep 17 00:00:00 2001 +From: Srinivas Kandagatla +Date: Thu, 10 Aug 2017 13:36:16 +0200 +Subject: [PATCH 29/39] conf/ucm: DB410c-HiFi: add CIC selection + +This patch adds CIC selection controls which have been added recently to +the kernel to select mic source. + +Without this patch user has to manually select the control to record +from DMIC or AMIC. + +Signed-off-by: Srinivas Kandagatla +Signed-off-by: Takashi Iwai +--- + src/conf/ucm/DB410c/HiFi | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/conf/ucm/DB410c/HiFi b/src/conf/ucm/DB410c/HiFi +index f9cbcf05..dcb7ac98 100644 +--- a/src/conf/ucm/DB410c/HiFi ++++ b/src/conf/ucm/DB410c/HiFi +@@ -108,6 +108,7 @@ SectionDevice."Handset" { + EnableSequence [ + cdev "hw:0" + cset "name='DEC1 MUX' ADC2" ++ cset "name='CIC1 MUX' AMIC" + cset "name='ADC2 Volume' 8" + cset "name='ADC2 MUX' INP2" + ] +@@ -130,6 +131,7 @@ SectionDevice."Primarymic" { + EnableSequence [ + cdev "hw:0" + cset "name='DEC1 MUX' ADC1" ++ cset "name='CIC1 MUX' AMIC" + cset "name='ADC1 Volume' 8" + ] + +@@ -150,6 +152,7 @@ SectionDevice."Secondarymic" { + EnableSequence [ + cdev "hw:0" + cset "name='DEC1 MUX' ADC2" ++ cset "name='CIC1 MUX' AMIC" + cset "name='ADC2 Volume' 8" + cset "name='ADC2 MUX' INP2" + ] +@@ -172,6 +175,7 @@ SectionDevice."DMIC" { + EnableSequence [ + cdev "hw:0" + cset "name='DEC1 MUX' DMIC1" ++ cset "name='CIC1 MUX' DMIC" + ] + + DisableSequence [ +-- +2.13.5 + + +From 97da58213a7f56850468fc74726f255a5739cb49 Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni +Date: Fri, 11 Aug 2017 23:24:03 +0200 +Subject: [PATCH 30/39] rawmidi: symbols: use rawmidi_virt only when available + +src/rawmidi/Makefile.am only brings rawmidi_virt.c into the build when +BUILD_SEQ is defined (i.e when --enable-seq is passed). However, +rawmidi_symbols.c unconditionally refers to _snd_module_rawmidi_virt, +defined in rawmidi_virt.c. + +This causes a link failure when BUILD_SEQ is disabled. For example +when linking ffmpeg against alsa-lib: + +/home/thomas/projets/buildroot/output/host/arm-buildroot-linux-uclibcgnueabi/sysroot/usr/lib/libasound.a(pcm_dmix.o): In function `snd_pcm_dmix_sync_ptr': +pcm_dmix.c:(.text+0x83c): warning: +/home/thomas/projets/buildroot/output/host/arm-buildroot-linux-uclibcgnueabi/sysroot/usr/lib/libasound.a(rawmidi_symbols.o):(.data+0x4): undefined reference to `_snd_module_rawmidi_virt' +collect2: error: ld returned 1 exit status + +To fix this, we make sure that rawmidi_symbols.c only uses +_snd_module_rawmidi_virt when available. + +Signed-off-by: Thomas Petazzoni +Signed-off-by: Takashi Iwai +--- + src/rawmidi/rawmidi_symbols.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/rawmidi/rawmidi_symbols.c b/src/rawmidi/rawmidi_symbols.c +index cdc06d7f..64734334 100644 +--- a/src/rawmidi/rawmidi_symbols.c ++++ b/src/rawmidi/rawmidi_symbols.c +@@ -21,11 +21,15 @@ + #ifndef PIC + + extern const char *_snd_module_rawmidi_hw; ++#ifdef BUILD_SEQ + extern const char *_snd_module_rawmidi_virt; ++#endif + + static const char **snd_rawmidi_open_objects[] = { + &_snd_module_rawmidi_hw, ++#ifdef BUILD_SEQ + &_snd_module_rawmidi_virt ++#endif + }; + + void *snd_rawmidi_open_symbols(void) +-- +2.13.5 + + +From 80bd4ce1478efdc08189c82a74da183da591c0fb Mon Sep 17 00:00:00 2001 +From: Pierre-Louis Bossart +Date: Wed, 16 Aug 2017 11:08:48 -0500 +Subject: [PATCH 31/39] conf: HdmiLpeAudio: add support for 3 devices + +The LPE Audio mode on BYT/CHT supports up to 3 devices, and also supports +IEC61937 passthrough. Add missing alsa-lib configurations so that +apps can use the usual -D'hdmi:CARD=X,DEV=Y,AES0=0x[4|6]' syntax, e.g. + +aplay -D'hdmi:CARD=0,DEV=2,AES0=0x6' -c2 -r48000 -fs16_le +ac3_surround_test.spdif + +Tested on Zotac PI330 with Onkyo receiver + +Signed-off-by: Pierre-Louis Bossart +Signed-off-by: Takashi Iwai +--- + src/conf/cards/HdmiLpeAudio.conf | 77 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 77 insertions(+) + +diff --git a/src/conf/cards/HdmiLpeAudio.conf b/src/conf/cards/HdmiLpeAudio.conf +index dae71fac..9fa30da0 100644 +--- a/src/conf/cards/HdmiLpeAudio.conf ++++ b/src/conf/cards/HdmiLpeAudio.conf +@@ -56,6 +56,83 @@ HdmiLpeAudio.pcm.hdmi.0 { + { + interface PCM + name "IEC958 Playback Default" ++ device 0 ++ lock true ++ preserve true ++ value [ $AES0 $AES1 $AES2 $AES3 ] ++ } ++ ] ++ } ++} ++ ++HdmiLpeAudio.pcm.hdmi.1 { ++ @args [ CARD AES0 AES1 AES2 AES3 ] ++ @args.CARD { ++ type string ++ } ++ @args.AES0 { ++ type integer ++ } ++ @args.AES1 { ++ type integer ++ } ++ @args.AES2 { ++ type integer ++ } ++ @args.AES3 { ++ type integer ++ } ++ type hooks ++ slave.pcm { ++ type hw ++ card $CARD ++ device 1 ++ } ++ hooks.0 { ++ type ctl_elems ++ hook_args [ ++ { ++ interface PCM ++ name "IEC958 Playback Default" ++ device 1 ++ lock true ++ preserve true ++ value [ $AES0 $AES1 $AES2 $AES3 ] ++ } ++ ] ++ } ++} ++ ++HdmiLpeAudio.pcm.hdmi.2 { ++ @args [ CARD AES0 AES1 AES2 AES3 ] ++ @args.CARD { ++ type string ++ } ++ @args.AES0 { ++ type integer ++ } ++ @args.AES1 { ++ type integer ++ } ++ @args.AES2 { ++ type integer ++ } ++ @args.AES3 { ++ type integer ++ } ++ type hooks ++ slave.pcm { ++ type hw ++ card $CARD ++ device 2 ++ } ++ hooks.0 { ++ type ctl_elems ++ hook_args [ ++ { ++ interface PCM ++ name "IEC958 Playback Default" ++ device 2 + lock true + preserve true + value [ $AES0 $AES1 $AES2 $AES3 ] +-- +2.13.5 + + +From 52826d4655fac9fa86600d5238391eb2c8ca8092 Mon Sep 17 00:00:00 2001 +From: Liam Girdwood +Date: Tue, 22 Aug 2017 10:16:05 +0100 +Subject: [PATCH 32/39] topology: Fix private data for BEs + +Private data was not being added to BEs. Fix this. + +Signed-off-by: Liam Girdwood +Signed-off-by: Takashi Iwai +--- + src/topology/data.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/topology/data.c b/src/topology/data.c +index 5b83b9fc..f96ff9bb 100644 +--- a/src/topology/data.c ++++ b/src/topology/data.c +@@ -50,7 +50,9 @@ struct snd_soc_tplg_private *get_priv_data(struct tplg_elem *elem) + case SND_TPLG_TYPE_DAI: + priv = &elem->dai->priv; + break; +- ++ case SND_TPLG_TYPE_BE: ++ priv = &elem->link->priv; ++ break; + default: + SNDERR("error: '%s': no support for private data for type %d\n", + elem->id, elem->type); +-- +2.13.5 + + +From 5efdabc1ab60f443f7183e50fea99510d0e3fe77 Mon Sep 17 00:00:00 2001 +From: Takashi Sakamoto +Date: Thu, 24 Aug 2017 10:48:35 +0900 +Subject: [PATCH 33/39] test: apply optimization for v4.14 kernel about changes + for TLV data handling on user-defined element set + +At kernel v4.14, in initial state, elements on user-defined sets have +write-only flag. When applications write TLV data, then the elements +get readable flag and the TLV data is available. Originally TLV data +is shared by elements in the same set, thus events are generated for +all of elements in the set by the write operation. + +Signed-off-by: Takashi Sakamoto +Signed-off-by: Takashi Iwai +--- + test/user-ctl-element-set.c | 84 +++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 73 insertions(+), 11 deletions(-) + +diff --git a/test/user-ctl-element-set.c b/test/user-ctl-element-set.c +index 8635c156..f3710732 100644 +--- a/test/user-ctl-element-set.c ++++ b/test/user-ctl-element-set.c +@@ -9,6 +9,7 @@ + + #include "../include/asoundlib.h" + #include ++#include + + struct elem_set_trial { + snd_ctl_t *handle; +@@ -28,6 +29,8 @@ struct elem_set_trial { + snd_ctl_elem_value_t *elem_data); + int (*allocate_elem_set_tlv)(struct elem_set_trial *trial, + unsigned int **tlv); ++ ++ bool tlv_readable; + }; + + struct chmap_entry { +@@ -420,9 +423,9 @@ static int check_event(struct elem_set_trial *trial, unsigned int mask, + continue; + /* + * I expect each event is generated separately to the same +- * element. ++ * element or several events are generated at once. + */ +- if (!(snd_ctl_event_elem_get_mask(event) & mask)) ++ if ((snd_ctl_event_elem_get_mask(event) & mask) != mask) + continue; + --expected_count; + } +@@ -561,6 +564,16 @@ static int check_elem_set_props(struct elem_set_trial *trial) + if (!snd_ctl_elem_info_is_locked(info)) + return -EIO; + ++ /* ++ * In initial state, any application can register TLV data for ++ * user-defined element set except for IEC 958 type, thus ++ * elements in any user-defined set should allow any write ++ * operation. ++ */ ++ if (trial->type != SND_CTL_ELEM_TYPE_IEC958 && ++ !snd_ctl_elem_info_is_tlv_writable(info)) ++ return -EIO; ++ + /* Check type-specific properties. */ + if (trial->check_elem_props != NULL) { + err = trial->check_elem_props(trial, info); +@@ -572,6 +585,25 @@ static int check_elem_set_props(struct elem_set_trial *trial) + err = snd_ctl_elem_unlock(trial->handle, id); + if (err < 0) + return err; ++ ++ /* ++ * Till kernel v4.14, ALSA control core allows elements in any ++ * user-defined set to have TLV_READ flag even if they have no ++ * TLV data in their initial state. In this case, any read ++ * operation for TLV data should return -ENXIO. ++ */ ++ if (snd_ctl_elem_info_is_tlv_readable(info)) { ++ unsigned int data[32]; ++ err = snd_ctl_elem_tlv_read(trial->handle, trial->id, ++ data, sizeof(data)); ++ if (err >= 0) ++ return -EIO; ++ if (err != -ENXIO) ++ return err; ++ ++ trial->tlv_readable = true; ++ } ++ + } + + return 0; +@@ -619,6 +651,8 @@ static int check_elems(struct elem_set_trial *trial) + static int check_tlv(struct elem_set_trial *trial) + { + unsigned int *tlv; ++ int mask; ++ unsigned int count; + unsigned int len; + unsigned int *curr; + int err; +@@ -644,6 +678,36 @@ static int check_tlv(struct elem_set_trial *trial) + if (err < 0) + goto end; + ++ /* ++ * Since kernel v4.14, any write operation to an element in user-defined ++ * set can change state of the other elements in the same set. In this ++ * case, any TLV data is firstly available after the operation. ++ */ ++ if (!trial->tlv_readable) { ++ mask = SND_CTL_EVENT_MASK_INFO | SND_CTL_EVENT_MASK_TLV; ++ count = trial->element_count; ++ } else { ++ mask = SND_CTL_EVENT_MASK_TLV; ++ count = 1; ++ } ++ err = check_event(trial, mask, count); ++ if (err < 0) ++ goto end; ++ if (!trial->tlv_readable) { ++ snd_ctl_elem_info_t *info; ++ snd_ctl_elem_info_alloca(&info); ++ ++ snd_ctl_elem_info_set_id(info, trial->id); ++ err = snd_ctl_elem_info(trial->handle, info); ++ if (err < 0) ++ return err; ++ if (!snd_ctl_elem_info_is_tlv_readable(info)) ++ return -EIO; ++ ++ /* Now TLV data is available for this element set. */ ++ trial->tlv_readable = true; ++ } ++ + err = snd_ctl_elem_tlv_read(trial->handle, trial->id, curr, len); + if (err < 0) + goto end; +@@ -690,6 +754,7 @@ int main(void) + trial.change_elem_members = change_bool_elem_members; + trial.allocate_elem_set_tlv = + allocate_bool_elem_set_tlv; ++ trial.tlv_readable = false; + break; + case SND_CTL_ELEM_TYPE_INTEGER: + trial.element_count = 900; +@@ -703,6 +768,7 @@ int main(void) + trial.change_elem_members = change_int_elem_members; + trial.allocate_elem_set_tlv = + allocate_int_elem_set_tlv; ++ trial.tlv_readable = false; + break; + case SND_CTL_ELEM_TYPE_ENUMERATED: + trial.element_count = 900; +@@ -715,6 +781,7 @@ int main(void) + trial.check_elem_props = check_enum_elem_props; + trial.change_elem_members = change_enum_elem_members; + trial.allocate_elem_set_tlv = NULL; ++ trial.tlv_readable = false; + break; + case SND_CTL_ELEM_TYPE_BYTES: + trial.element_count = 900; +@@ -728,6 +795,7 @@ int main(void) + trial.change_elem_members = change_bytes_elem_members; + trial.allocate_elem_set_tlv = + allocate_bytes_elem_set_tlv; ++ trial.tlv_readable = false; + break; + case SND_CTL_ELEM_TYPE_IEC958: + trial.element_count = 1; +@@ -740,6 +808,7 @@ int main(void) + trial.check_elem_props = NULL; + trial.change_elem_members = change_iec958_elem_members; + trial.allocate_elem_set_tlv = NULL; ++ trial.tlv_readable = false; + break; + case SND_CTL_ELEM_TYPE_INTEGER64: + default: +@@ -754,6 +823,7 @@ int main(void) + trial.change_elem_members = change_int64_elem_members; + trial.allocate_elem_set_tlv = + allocate_int64_elem_set_tlv; ++ trial.tlv_readable = false; + break; + } + +@@ -784,7 +854,7 @@ int main(void) + /* Check properties of each element in this element set. */ + err = check_elem_set_props(&trial); + if (err < 0) { +- printf("Fail to check propetries of each element with " ++ printf("Fail to check properties of each element with " + "%s type.\n", + snd_ctl_elem_type_name(trial.type)); + break; +@@ -822,14 +892,6 @@ int main(void) + snd_ctl_elem_type_name(trial.type)); + break; + } +- err = check_event(&trial, SND_CTL_EVENT_MASK_TLV, 1); +- if (err < 0) { +- printf("Fail to check an event to change TLV" +- "data of an an element set with %s " +- "type.\n", +- snd_ctl_elem_type_name(trial.type)); +- break; +- } + } + + /* Test an operation to remove elements in this element set. */ +-- +2.13.5 + + +From 8d6169514519a3f3246ad09dd1281e3a7d854d42 Mon Sep 17 00:00:00 2001 +From: Liam Girdwood +Date: Tue, 12 Sep 2017 21:47:42 +0100 +Subject: [PATCH 34/39] topology: fix usage of SND_TPLG_INDEX_ALL when checking + routes + +Make sure SND_TPLG_INDEX_ALL is used correctly when checking routes so +that connecting routes of different indexes does not emit any warnings. + +Signed-off-by: Liam Girdwood +Signed-off-by: Takashi Iwai +--- + src/topology/dapm.c | 4 ++-- + src/topology/elem.c | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/topology/dapm.c b/src/topology/dapm.c +index 66892a66..0ddbf965 100644 +--- a/src/topology/dapm.c ++++ b/src/topology/dapm.c +@@ -279,7 +279,7 @@ int tplg_build_routes(snd_tplg_t *tplg) + + } + if (!tplg_elem_lookup(&tplg->widget_list, route->sink, +- SND_TPLG_TYPE_DAPM_WIDGET, elem->index)) { ++ SND_TPLG_TYPE_DAPM_WIDGET, SND_TPLG_INDEX_ALL)) { + SNDERR("warning: undefined sink widget/stream '%s'\n", + route->sink); + } +@@ -302,7 +302,7 @@ int tplg_build_routes(snd_tplg_t *tplg) + + } + if (!tplg_elem_lookup(&tplg->widget_list, route->source, +- SND_TPLG_TYPE_DAPM_WIDGET, elem->index)) { ++ SND_TPLG_TYPE_DAPM_WIDGET, SND_TPLG_INDEX_ALL)) { + SNDERR("warning: Undefined source widget/stream '%s'\n", + route->source); + } +diff --git a/src/topology/elem.c b/src/topology/elem.c +index 89a4ac9f..9a7c7b75 100644 +--- a/src/topology/elem.c ++++ b/src/topology/elem.c +@@ -123,7 +123,7 @@ struct tplg_elem *tplg_elem_lookup(struct list_head *base, const char* id, + return elem; + /* SND_TPLG_INDEX_ALL is the default value "0" and applicable + for all use cases */ +- if ((elem->index != SND_TPLG_INDEX_ALL) ++ if ((index != SND_TPLG_INDEX_ALL) + && (elem->index > index)) + break; + } +-- +2.13.5 + + +From 6a617cc719d553ad8eb96308b7f3b94f5a53d243 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?J=C3=B6rg=20Krause?= +Date: Wed, 13 Sep 2017 16:21:10 +0200 +Subject: [PATCH 35/39] pcm: softvol: add support for S24_LE +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Tested with the Wolfson WM8524 DAC on a i.MX6UL board and the following +ALSA configuration file using the pcm test utility from alsa-lib: + +""" +$ cat /etc/asound.conf +pcm.!default { + type plug + slave.pcm "softvol" +} +pcm.softvol { + type softvol + slave { + pcm "hw:0" + } + control { + name "Master" + card 0 + } +} +ctl.!default { + type hw + card 0 +} +ctl.softvol { + type hw + card 0 +} + +$ pcm -D softvol -o S24_LE -c 2 -r 48000 +""" + +The data in the Synchronous Audio Interface (SAI) of the i.MX6UL is +aligned the following way: + +""" +31 30 29 28 | 27 26 25 24 | 23 22 21 20 | .. | 3 2 1 0 +## ## ## ## ## ## ## ## [ DATA[23:0] ] +""" + +Signed-off-by: Jörg Krause +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_softvol.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 53 insertions(+), 3 deletions(-) + +diff --git a/src/pcm/pcm_softvol.c b/src/pcm/pcm_softvol.c +index 1fe5784d..68a35b56 100644 +--- a/src/pcm/pcm_softvol.c ++++ b/src/pcm/pcm_softvol.c +@@ -251,6 +251,44 @@ static inline short MULTI_DIV_short(short a, unsigned int b, int swap) + } \ + } \ + } while (0) ++ ++#define CONVERT_AREA_S24_LE() do { \ ++ unsigned int ch, fr; \ ++ int *src, *dst; \ ++ int tmp; \ ++ for (ch = 0; ch < channels; ch++) { \ ++ src_area = &src_areas[ch]; \ ++ dst_area = &dst_areas[ch]; \ ++ src = snd_pcm_channel_area_addr(src_area, src_offset); \ ++ dst = snd_pcm_channel_area_addr(dst_area, dst_offset); \ ++ src_step = snd_pcm_channel_area_step(src_area) \ ++ / sizeof(int); \ ++ dst_step = snd_pcm_channel_area_step(dst_area) \ ++ / sizeof(int); \ ++ GET_VOL_SCALE; \ ++ fr = frames; \ ++ if (! vol_scale) { \ ++ while (fr--) { \ ++ *dst = 0; \ ++ dst += dst_step; \ ++ } \ ++ } else if (vol_scale == 0xffff) { \ ++ while (fr--) { \ ++ *dst = *src; \ ++ src += dst_step; \ ++ dst += src_step; \ ++ } \ ++ } else { \ ++ while (fr--) { \ ++ tmp = *src << 8; \ ++ tmp = (signed int) tmp >> 8; \ ++ *dst = MULTI_DIV_24(tmp, vol_scale); \ ++ src += dst_step; \ ++ dst += src_step; \ ++ } \ ++ } \ ++ } \ ++} while (0) + + #define GET_VOL_SCALE \ + switch (ch) { \ +@@ -315,6 +353,10 @@ static void softvol_convert_stereo_vol(snd_pcm_softvol_t *svol, + CONVERT_AREA(int, + !snd_pcm_format_cpu_endian(svol->sformat)); + break; ++ case SND_PCM_FORMAT_S24_LE: ++ /* 24bit samples */ ++ CONVERT_AREA_S24_LE(); ++ break; + case SND_PCM_FORMAT_S24_3LE: + CONVERT_AREA_S24_3LE(); + break; +@@ -366,6 +408,10 @@ static void softvol_convert_mono_vol(snd_pcm_softvol_t *svol, + CONVERT_AREA(int, + !snd_pcm_format_cpu_endian(svol->sformat)); + break; ++ case SND_PCM_FORMAT_S24_LE: ++ /* 24bit samples */ ++ CONVERT_AREA_S24_LE(); ++ break; + case SND_PCM_FORMAT_S24_3LE: + CONVERT_AREA_S24_3LE(); + break; +@@ -422,6 +468,7 @@ static int snd_pcm_softvol_hw_refine_cprepare(snd_pcm_t *pcm, + { + (1ULL << SND_PCM_FORMAT_S16_LE) | + (1ULL << SND_PCM_FORMAT_S16_BE) | ++ (1ULL << SND_PCM_FORMAT_S24_LE) | + (1ULL << SND_PCM_FORMAT_S32_LE) | + (1ULL << SND_PCM_FORMAT_S32_BE), + (1ULL << (SND_PCM_FORMAT_S24_3LE - 32)) +@@ -577,10 +624,11 @@ static int snd_pcm_softvol_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * param + if (slave->format != SND_PCM_FORMAT_S16_LE && + slave->format != SND_PCM_FORMAT_S16_BE && + slave->format != SND_PCM_FORMAT_S24_3LE && ++ slave->format != SND_PCM_FORMAT_S24_LE && + slave->format != SND_PCM_FORMAT_S32_LE && + slave->format != SND_PCM_FORMAT_S32_BE) { +- SNDERR("softvol supports only S16_LE, S16_BE, S24_3LE, S32_LE " +- " or S32_BE"); ++ SNDERR("softvol supports only S16_LE, S16_BE, S24_LE, S24_3LE, " ++ "S32_LE or S32_BE"); + return -EINVAL; + } + svol->sformat = slave->format; +@@ -863,6 +911,7 @@ int snd_pcm_softvol_open(snd_pcm_t **pcmp, const char *name, + sformat != SND_PCM_FORMAT_S16_LE && + sformat != SND_PCM_FORMAT_S16_BE && + sformat != SND_PCM_FORMAT_S24_3LE && ++ sformat != SND_PCM_FORMAT_S24_LE && + sformat != SND_PCM_FORMAT_S32_LE && + sformat != SND_PCM_FORMAT_S32_BE) + return -EINVAL; +@@ -1082,9 +1131,10 @@ int _snd_pcm_softvol_open(snd_pcm_t **pcmp, const char *name, + sformat != SND_PCM_FORMAT_S16_LE && + sformat != SND_PCM_FORMAT_S16_BE && + sformat != SND_PCM_FORMAT_S24_3LE && ++ sformat != SND_PCM_FORMAT_S24_LE && + sformat != SND_PCM_FORMAT_S32_LE && + sformat != SND_PCM_FORMAT_S32_BE) { +- SNDERR("only S16_LE, S16_BE, S24_3LE, S32_LE or S32_BE format is supported"); ++ SNDERR("only S16_LE, S16_BE, S24_LE, S24_3LE, S32_LE or S32_BE format is supported"); + snd_config_delete(sconf); + return -EINVAL; + } +-- +2.13.5 + + +From baed295faafb076d380392fa938234a7ec426dfc Mon Sep 17 00:00:00 2001 +From: Antonio Ospite +Date: Thu, 28 Sep 2017 15:46:15 +0200 +Subject: [PATCH 36/39] seq: fix snd_seq_set_queue_tempo() usage example in the + documentation + +snd_seq_set_queue_tempo() requires a queue id as the second argument, +fix the example in documentation to reflect that. + +Also add the queue id as an argument of the set_tempo() function, just +to keep the whole example compilable. + +Signed-off-by: Antonio Ospite +Signed-off-by: Takashi Iwai +--- + src/seq/seq.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/seq/seq.c b/src/seq/seq.c +index d5ed1c6a..808c7915 100644 +--- a/src/seq/seq.c ++++ b/src/seq/seq.c +@@ -452,13 +452,13 @@ For setting these tempo parameters, use #snd_seq_queue_tempo_t record. + For example, to set the tempo of the queue q to + 48 PPQ, 60 BPM, + \code +-void set_tempo(snd_seq_t *handle) ++void set_tempo(snd_seq_t *handle, int queue) + { + snd_seq_queue_tempo_t *tempo; + snd_seq_queue_tempo_alloca(&tempo); + snd_seq_queue_tempo_set_tempo(tempo, 1000000); // 60 BPM + snd_seq_queue_tempo_set_ppq(tempo, 48); // 48 PPQ +- snd_seq_set_queue_tempo(handle, tempo); ++ snd_seq_set_queue_tempo(handle, queue, tempo); + } + \endcode + +-- +2.13.5 + + +From 8c0b17bca3d641dc86d35eb1b97fae5fe4080984 Mon Sep 17 00:00:00 2001 +From: Antonio Ospite +Date: Tue, 26 Sep 2017 16:44:49 +0200 +Subject: [PATCH 37/39] test/seq-decoder: enable timestamping for external + subscribers + +Events sent by external clients subscribed to the input port are not +timestamped. + +This inconsistent behavior may surprise newbies who look at seq-decoder as +a reference example. + +See the example below using "vkeybd --addr 128:0" to connect to seq-decoder, +the events sent by vkeybd are on a different queue with no timestamps: + + ... + EVENT>>> Type = 66, flags = 0x0, time = 0 ticks + Source = 0.1, dest = 128.0, queue = 253 + Event = Port Subscribed; 129:0 -> 128:0 + EVENT>>> Type = 66, flags = 0x1, time = 4.829712627 + Source = 0.1, dest = 128.0, queue = 0 + Event = Port Subscribed; 129:0 -> 128:0 + EVENT>>> Type = 10, flags = 0x0, time = 0 ticks + Source = 129.0, dest = 128.0, queue = 253 + Event = Controller; ch=0, param=0, value=0 + EVENT>>> Type = 11, flags = 0x0, time = 0 ticks + Source = 129.0, dest = 128.0, queue = 253 + Event = Program Change; ch=0, program=0 + ... + +After the change events are on the main queue and are timestamped: + + ... + EVENT>>> Type = 66, flags = 0x1, time = 4.280907223 + Source = 0.1, dest = 128.0, queue = 0 + Event = Port Subscribed; 129:0 -> 128:0 + EVENT>>> Type = 66, flags = 0x1, time = 4.280912063 + Source = 0.1, dest = 128.0, queue = 0 + Event = Port Subscribed; 129:0 -> 128:0 + EVENT>>> Type = 10, flags = 0x1, time = 4.280990702 + Source = 129.0, dest = 128.0, queue = 0 + Event = Controller; ch=0, param=0, value=0 + EVENT>>> Type = 11, flags = 0x1, time = 4.280994862 + Source = 129.0, dest = 128.0, queue = 0 + Event = Program Change; ch=0, program=0 + ... + +Signed-off-by: Antonio Ospite +Signed-off-by: Takashi Iwai +--- + test/seq-decoder.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/test/seq-decoder.c b/test/seq-decoder.c +index b110e98d..38755553 100644 +--- a/test/seq-decoder.c ++++ b/test/seq-decoder.c +@@ -283,6 +283,12 @@ void event_decoder(snd_seq_t *handle, int argc, char *argv[]) + snd_seq_port_info_set_name(pinfo, "Input"); + snd_seq_port_info_set_type(pinfo, SND_SEQ_PORT_TYPE_MIDI_GENERIC); + snd_seq_port_info_set_capability(pinfo, SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_WRITE); ++ ++ /* Enable timestamping for events sent by external subscribers. */ ++ snd_seq_port_info_set_timestamping(pinfo, 1); ++ snd_seq_port_info_set_timestamp_real(pinfo, 1); ++ snd_seq_port_info_set_timestamp_queue(pinfo, queue); ++ + if ((err = snd_seq_create_port(handle, pinfo)) < 0) { + fprintf(stderr, "Cannot create input port: %s\n", snd_strerror(err)); + return; +-- +2.13.5 + + +From 98d2c12ac2f8dc7e92790e927f472e26459d3852 Mon Sep 17 00:00:00 2001 +From: Timo Wischer +Date: Thu, 5 Oct 2017 16:25:23 +0200 +Subject: [PATCH 38/39] ctl: ext: Fail with error code if + snd_ctl_ext_callback::read_event() callback is not defined + +The snd_ctl_ext_callback::read_event() callback is only optional +if no poll descriptor was given via +snd_ctl_ext_t::poll_fd +or +snd_ctl_ext_callback::snd_ctl_ext_poll_descriptors(). + +If a poll descriptor is given the +snd_ctl_ext_callback::read_event() +callback has also to be defined +because there is no minigful default behavior. + +This callback will be called when ever the poll() on +the file descriptor indicates that there is an event pending. +Therefore returning a 0 which indicates that there is no event makes no +sense. + +Signed-off-by: Timo Wischer +Signed-off-by: Takashi Iwai +--- + src/control/control_ext.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/src/control/control_ext.c b/src/control/control_ext.c +index 56552fa1..d7de8e84 100644 +--- a/src/control/control_ext.c ++++ b/src/control/control_ext.c +@@ -415,8 +415,12 @@ static int snd_ctl_ext_read(snd_ctl_t *handle, snd_ctl_event_t *event) + { + snd_ctl_ext_t *ext = handle->private_data; + +- memset(event, 0, sizeof(*event)); +- return ext->callback->read_event(ext, &event->data.elem.id, &event->data.elem.mask); ++ if (ext->callback->read_event) { ++ memset(event, 0, sizeof(*event)); ++ return ext->callback->read_event(ext, &event->data.elem.id, &event->data.elem.mask); ++ } ++ ++ return -EINVAL; + } + + static int snd_ctl_ext_poll_descriptors_count(snd_ctl_t *handle) +-- +2.13.5 + + +From 996dd33b5f0df06d0b1fdd8f43b7a212c26e2a27 Mon Sep 17 00:00:00 2001 +From: Tanu Kaskinen +Date: Wed, 4 Oct 2017 22:44:00 +0300 +Subject: [PATCH 39/39] conf: HdmiLpeAudio: remove the "front" pcm definition + +PulseAudio assumes that the "front" pcm device always refers to an +analog device, not HDMI. While that assumption is not really valid, the +reality is that without that assumption PulseAudio can't know whether +"front" and "hdmi" refer to a different or the same device. + +The HDMI LPE driver doesn't allow audio streaming while the HDMI cable +is unplugged, so PulseAudio has to know when it's plugged in and when +it's not. If both "front" and "hdmi" devices exist, PulseAudio will +notice that HDMI is unplugged, but it doesn't know that "front" refers +to the same device, and PulseAudio will try to use the "front" device +with bad consequences. The kernel driver's refusal to stream any audio +makes PulseAudio enter an infinite loop and then the kernel kills +PulseAudio, because it consumes too much CPU time in a realtime thread. + +While the looping in PulseAudio could probably be fixed, that wouldn't +change the fact that PulseAudio thinks that there is an analog device. I +believe it's best to avoid having the same device as both "front" and +"hdmi" in alsa-lib. + +I removed also the surround configuration includes. I don't think they +had any effect anyway, so I wonder why they were there in the first +place. + +BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=100488 +Signed-off-by: Takashi Iwai +--- + src/conf/cards/HdmiLpeAudio.conf | 24 ------------------------ + 1 file changed, 24 deletions(-) + +diff --git a/src/conf/cards/HdmiLpeAudio.conf b/src/conf/cards/HdmiLpeAudio.conf +index 9fa30da0..a1e493da 100644 +--- a/src/conf/cards/HdmiLpeAudio.conf ++++ b/src/conf/cards/HdmiLpeAudio.conf +@@ -2,30 +2,6 @@ + # Configuration for the Intel HDMI/DP LPE audio + # + +- +- +-HdmiLpeAudio.pcm.front.0 { +- @args [ CARD ] +- @args.CARD { +- type string +- } +- type softvol +- slave.pcm { +- type hw +- card $CARD +- } +- control { +- name "PCM Playback Volume" +- card $CARD +- } +-} +- +- +- +- +- +- +- + + + HdmiLpeAudio.pcm.hdmi.0 { +-- +2.13.5 + +From 7f3ad37fd7e9327542be7f467ad337dd7398e2b7 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Sun, 22 Oct 2017 15:02:19 +0200 +Subject: [PATCH] topology: fix coverity issues + +--- + src/topology/ctl.c | 6 +++--- + src/topology/dapm.c | 7 ++++++- + src/topology/data.c | 7 +++---- + src/topology/elem.c | 4 +++- + 4 files changed, 15 insertions(+), 9 deletions(-) + +diff --git a/src/topology/ctl.c b/src/topology/ctl.c +index e73d9eb7..9dd88db6 100644 +--- a/src/topology/ctl.c ++++ b/src/topology/ctl.c +@@ -130,7 +130,7 @@ static int tplg_build_mixer_control(snd_tplg_t *tplg, + list_for_each(pos, base) { + + ref = list_entry(pos, struct tplg_ref, list); +- if (ref->id == NULL || ref->elem) ++ if (ref->elem) + continue; + + if (ref->type == SND_TPLG_TYPE_TLV) { +@@ -180,7 +180,7 @@ static int tplg_build_enum_control(snd_tplg_t *tplg, + list_for_each(pos, base) { + + ref = list_entry(pos, struct tplg_ref, list); +- if (ref->id == NULL || ref->elem) ++ if (ref->elem) + continue; + + if (ref->type == SND_TPLG_TYPE_TEXT) { +@@ -216,7 +216,7 @@ static int tplg_build_bytes_control(snd_tplg_t *tplg, struct tplg_elem *elem) + list_for_each(pos, base) { + + ref = list_entry(pos, struct tplg_ref, list); +- if (ref->id == NULL || ref->elem) ++ if (ref->elem) + continue; + + if (ref->type == SND_TPLG_TYPE_DATA) { +diff --git a/src/topology/dapm.c b/src/topology/dapm.c +index 0ddbf965..e5d473a8 100644 +--- a/src/topology/dapm.c ++++ b/src/topology/dapm.c +@@ -428,7 +428,7 @@ int tplg_parse_dapm_graph(snd_tplg_t *tplg, snd_config_t *cfg, + snd_config_t *n; + int err; + const char *graph_id, *val = NULL; +- int index; ++ int index = -1; + + if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) { + SNDERR("error: compound is expected for dapm graph definition\n"); +@@ -452,6 +452,11 @@ int tplg_parse_dapm_graph(snd_tplg_t *tplg, snd_config_t *cfg, + } + + if (strcmp(id, "lines") == 0) { ++ if (index < 0) { ++ SNDERR("error: failed to parse dapm graph %s, missing index\n", ++ graph_id); ++ return -EINVAL; ++ } + err = tplg_parse_routes(tplg, n, index); + if (err < 0) { + SNDERR("error: failed to parse dapm graph %s\n", +diff --git a/src/topology/data.c b/src/topology/data.c +index f96ff9bb..6b7c3f6c 100644 +--- a/src/topology/data.c ++++ b/src/topology/data.c +@@ -132,7 +132,6 @@ err: + static void dump_priv_data(struct tplg_elem *elem) + { + struct snd_soc_tplg_private *priv = elem->data; +- unsigned char *p = (unsigned char *)priv->data; + unsigned int i, j = 0; + + tplg_dbg(" elem size = %d, priv data size = %d\n", +@@ -366,7 +365,7 @@ static struct tplg_elem *get_tokens(snd_tplg_t *tplg, struct tplg_elem *elem) + + ref = list_entry(pos, struct tplg_ref, list); + +- if (!ref->id || ref->type != SND_TPLG_TYPE_TOKEN) ++ if (ref->type != SND_TPLG_TYPE_TOKEN) + continue; + + if (!ref->elem) { +@@ -390,7 +389,7 @@ static bool has_tuples(struct tplg_elem *elem) + list_for_each(pos, base) { + + ref = list_entry(pos, struct tplg_ref, list); +- if (ref->id && ref->type == SND_TPLG_TYPE_TUPLE) ++ if (ref->type == SND_TPLG_TYPE_TUPLE) + return true; + } + +@@ -504,7 +503,7 @@ static int build_tuples(snd_tplg_t *tplg, struct tplg_elem *elem) + + ref = list_entry(pos, struct tplg_ref, list); + +- if (!ref->id || ref->type != SND_TPLG_TYPE_TUPLE) ++ if (ref->type != SND_TPLG_TYPE_TUPLE) + continue; + + tplg_dbg("tuples '%s' used by data '%s'\n", ref->id, elem->id); +diff --git a/src/topology/elem.c b/src/topology/elem.c +index 9a7c7b75..16ad4423 100644 +--- a/src/topology/elem.c ++++ b/src/topology/elem.c +@@ -178,8 +178,10 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg, + if (snd_config_get_id(n, &id)) + continue; + if (strcmp(id, "index") == 0) { +- if (snd_config_get_string(n, &val) < 0) ++ if (snd_config_get_string(n, &val) < 0) { ++ free(elem); + return NULL; ++ } + elem->index = atoi(val); + } + } +-- +2.13.5 + diff --git a/SOURCES/asound.conf b/SOURCES/asound.conf new file mode 100644 index 0000000..da7ab7c --- /dev/null +++ b/SOURCES/asound.conf @@ -0,0 +1,3 @@ +# +# Place your global alsa-lib configuration here... +# diff --git a/SOURCES/modprobe-dist-alsa.conf b/SOURCES/modprobe-dist-alsa.conf new file mode 100644 index 0000000..cf31fa6 --- /dev/null +++ b/SOURCES/modprobe-dist-alsa.conf @@ -0,0 +1,9 @@ +# ALSA Sound Support +# +# We want to ensure that snd-seq is always loaded for those who want to use +# the sequencer interface, but we can't do this automatically through udev +# at the moment...so we have this rule (just for the moment). +# +# Remove the following line if you don't want the sequencer. + +install snd-pcm /sbin/modprobe --ignore-install snd-pcm && /sbin/modprobe snd-seq diff --git a/SOURCES/modprobe-dist-oss.conf b/SOURCES/modprobe-dist-oss.conf new file mode 100644 index 0000000..21f93cc --- /dev/null +++ b/SOURCES/modprobe-dist-oss.conf @@ -0,0 +1,8 @@ +# OSS Sound Support +# This has been disabled in F11 onwards because it can interfere with the +# PulseAudio sound service (a legacy OSS application can prevent PulseAudio +# applications from playing sound by preventing PulseAudio from (re-)opening +# the sound device). To re-enable support, copy this file to +# the /etc/modprobe.d directory. +# +install snd-pcm /sbin/modprobe --ignore-install snd-pcm && /sbin/modprobe snd-pcm-oss && /sbin/modprobe snd-seq-device && /sbin/modprobe snd-seq-oss diff --git a/SPECS/alsa-lib.spec b/SPECS/alsa-lib.spec new file mode 100644 index 0000000..065b8a6 --- /dev/null +++ b/SPECS/alsa-lib.spec @@ -0,0 +1,476 @@ +#define prever rc3 +#define prever_dot .rc3 +#define postver a + +Summary: The Advanced Linux Sound Architecture (ALSA) library +Name: alsa-lib +Version: 1.1.4.1 +Release: 2%{?prever_dot}%{?dist} +License: LGPLv2+ +Group: System Environment/Libraries +URL: http://www.alsa-project.org/ + +Source: ftp://ftp.alsa-project.org/pub/lib/%{name}-%{version}%{?prever}%{?postver}.tar.bz2 +Source10: asound.conf +Source11: modprobe-dist-alsa.conf +Source12: modprobe-dist-oss.conf +Patch0: alsa-lib-1.1.4.1-post.patch +Patch1: alsa-lib-1.1.0-config.patch + +BuildRequires: doxygen +BuildRequires: autoconf automake libtool +Requires(post): /sbin/ldconfig, coreutils + +%description +The Advanced Linux Sound Architecture (ALSA) provides audio and MIDI +functionality to the Linux operating system. + +This package includes the ALSA runtime libraries to simplify application +programming and provide higher level functionality as well as support for +the older OSS API, providing binary compatibility for most OSS programs. + +%package devel +Summary: Development files from the ALSA library +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} +Requires: pkgconfig + +%description devel +The Advanced Linux Sound Architecture (ALSA) provides audio and MIDI +functionality to the Linux operating system. + +This package includes the ALSA development libraries for developing +against the ALSA libraries and interfaces. + +%prep +%setup -q -n %{name}-%{version}%{?prever}%{?postver} +%patch0 -p1 -b .post +%patch1 -p1 -b .config +autoreconf -f -i + +%build +%configure --disable-aload --with-plugindir=%{_libdir}/alsa-lib --disable-alisp + +# Remove useless /usr/lib64 rpath on 64bit archs +sed -i 's|^hardcode_libdir_flag_spec=.*|hardcode_libdir_flag_spec=""|g' libtool +sed -i 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' libtool + +make %{?_smp_mflags} V=1 +make doc + +%install +make DESTDIR=%{buildroot} install + +# We need the library to be available even before /usr might be mounted +mkdir -p %{buildroot}/%{_lib} +mv %{buildroot}%{_libdir}/libasound.so.* %{buildroot}/%{_lib} +ln -snf ../../%{_lib}/libasound.so.2 %{buildroot}%{_libdir}/libasound.so + +# Install global configuration files +mkdir -p -m 755 %{buildroot}/etc +install -p -m 644 %{SOURCE10} %{buildroot}/etc + +# Install the modprobe files for ALSA +mkdir -p -m 755 %{buildroot}/lib/modprobe.d/ +install -p -m 644 %{SOURCE11} %{buildroot}/lib/modprobe.d/dist-alsa.conf +# bug#926973, place this file to the doc directory +mkdir -p -m 755 %{buildroot}%{_defaultdocdir}/%{name}/ +install -p -m 644 %{SOURCE12} %{buildroot}%{_defaultdocdir}/%{name}/modprobe-dist-oss.conf + +# Create UCM directory +mkdir -p %{buildroot}/%{_datadir}/alsa/ucm +# Remove all UCM files (should be selected by architecture) +rm -rf %{buildroot}/%{_datadir}/alsa/ucm/* +# Remove smixer .so modules +rm -rf %{buildroot}/%{_libdir}/alsa-lib/smixer + +#Remove libtool archives. +find %{buildroot} -name '*.la' -delete + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + +%files +%defattr(-,root,root,-) +%doc COPYING TODO doc/asoundrc.txt +# file is as old as 0.2.0 / Red Hat bugzilla #510212 +#doc Changelog +%{_defaultdocdir}/%{name}/modprobe-dist-oss.conf +%config %{_sysconfdir}/asound.conf +/%{_lib}/libasound.so.* +%{_bindir}/aserver +#%{_libdir}/alsa-lib/ +%{_datadir}/alsa/ +/lib/modprobe.d/dist-* + +%files devel +%defattr(-,root,root,-) +%doc doc/doxygen/ +%{_includedir}/alsa/ +%{_includedir}/sys/asoundlib.h +%{_libdir}/libasound.so +%{_libdir}/pkgconfig/alsa.pc +%{_datadir}/aclocal/alsa.m4 + +%changelog +* Sun Oct 22 2017 Jaroslav Kysela - 1.1.4.1-2 +- Updated to 1.1.4.1 +- Resolves: rhbz#1485645 + +* Wed Mar 1 2017 Jaroslav Kysela - 1.1.3-3 +- Updated to 1.1.3 +- Resolves: rhbz#1399508 + +* Mon Jun 6 2016 Jaroslav Kysela - 1.1.1-1 +- Updated to 1.1.1 +- Resolves: rhbz#1297932 + +* Tue Sep 16 2014 Jaroslav Kysela - 1.0.28-2 +- Fix minor coverity bug + +* Mon Sep 15 2014 Jaroslav Kysela - 1.0.28-1 +- Updated to 1.0.28 +- Resolves: rhbz#1112204 + +* Fri Jan 24 2014 Daniel Mach - 1.0.27.2-3 +- Mass rebuild 2014-01-24 + +* Fri Dec 27 2013 Daniel Mach - 1.0.27.2-2 +- Mass rebuild 2013-12-27 + +* Mon Jul 08 2013 Jaroslav Kysela - 1.0.27.2-1 +- Updated to 1.0.27.2 + +* Thu May 30 2013 Jaroslav Kysela - 1.0.27.1-2 +- Fixed bug#953352 + +* Tue May 21 2013 Jaroslav Kysela - 1.0.27.1-1 +- Updated to 1.0.27.1 + +* Tue May 07 2013 Rex Dieter 1.0.27-3 +- pull in upstream fix for building in C90 mode + +* Thu Apr 11 2013 Jaroslav Kysela - 1.0.27-2 +- move dist-oss.conf to doc as modprobe-dist-oss.conf + +* Thu Apr 11 2013 Jaroslav Kysela - 1.0.27-1 +- Updated to 1.0.27 + +* Wed Apr 03 2013 Stephen Gallagher - 1.0.26-4 +- Add upstream patch to explicitly include sys/types.h + +* Wed Feb 13 2013 Fedora Release Engineering - 1.0.26-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Mon Dec 3 2012 Peter Robinson 1.0.26-2 +- Create and own ucm directory so alsaucm doesn't crash. +- Cleanup and modernise spec + +* Thu Sep 6 2012 Jaroslav Kysela - 1.0.26-1 +- Updated to 1.0.26 + +* Thu Jul 26 2012 Michael Schwendt - 1.0.25-6 +- Don't package ancient ChangeLog that ends at alsa-lib 0.2.0 (#510212). + +* Wed Jul 18 2012 Fedora Release Engineering - 1.0.25-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Wed May 2 2012 Josh Boyer - 1.0.25-4 +- Install ALSA related module conf files + +* Wed Feb 1 2012 Jaroslav Kysela - 1.0.25-3 +- Remove the pulse audio configuration from /etc/asound.conf + +* Sat Jan 28 2012 Jaroslav Kysela - 1.0.25-1 +- Updated to 1.0.25 final + +* Thu Jan 12 2012 Fedora Release Engineering - 1.0.24-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Mon Feb 07 2011 Fedora Release Engineering - 1.0.24-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Fri Jan 28 2011 Jaroslav Kysela - 1.0.24-1 +- Updated to 1.0.24 final + +* Tue Nov 9 2010 Jochen Schmitt 1.0.23-2 +- Set plugindir to %%{_libdir}/alsa-lib (bz#651507) + +* Fri Apr 16 2010 Jaroslav Kysela - 1.0.23-1 +- Updated to 1.0.23 final + +* Mon Dec 28 2009 Jaroslav Kysela - 1.0.22-1 +- Updated to 1.0.22 final +- Fix file descriptor leak in pcm_hw plugin +- Fix sound distortions for S24_LE - softvol plugin + +* Wed Sep 9 2009 Jaroslav Kysela - 1.0.21-3 +- Add Speaker and Beep control names to mixer weight list +- Fix redhat bug #521988 + +* Wed Sep 2 2009 Jaroslav Kysela - 1.0.21-1 +- Updated to 1.0.21 final + +* Fri Jul 24 2009 Fedora Release Engineering - 1.0.20-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Wed May 6 2009 Jaroslav Kysela - 1.0.20-1 +- Updated to 1.0.20 final + +* Mon Feb 23 2009 Fedora Release Engineering - 1.0.19-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Wed Feb 4 2009 Jaroslav Kysela - 1.0.19-2 +- Make doxygen documentation same for all architectures (bz#465205) + +* Tue Jan 20 2009 Jaroslav Kysela - 1.0.19-1 +- Updated to 1.0.19 final + +* Tue Nov 4 2008 Jaroslav Kysela - 1.0.18-7 +- Updated to 1.0.18 final + +* Wed Sep 10 2008 Jaroslav Kysela - 1.0.18-6.rc3 +- fix /etc directory issue + +* Wed Sep 10 2008 Jaroslav Kysela - 1.0.18-5.rc3 +- move alsactl.conf to alsa-utils package + +* Wed Sep 10 2008 Jaroslav Kysela - 1.0.18-4.rc3 +- fixed spec file +- fixed package version number (1.0.18-3.rc3 was tagged by accident) + +* Wed Sep 10 2008 Jaroslav Kysela - 1.0.18-1.rc3 +- updated to 1.0.18rc3 +- moved /etc/alsa configuration files back to /usr/share/alsa +- removed pulse default patch (moved to /etc/asound.conf) +- added /etc/asound.conf and /etc/alsa/alsactl.conf +- disable /dev/aload device checking (obsolete for 2.6 kernels) + +* Fri Aug 15 2008 Jaroslav Kysela - 1.0.17-3 +- updated to 1.0.17a + +* Mon Jul 21 2008 Jaroslav Kysela - 1.0.17-2 +- added four patches from upstream (to better support pulseaudio) + +* Mon Jul 21 2008 Jaroslav Kysela - 1.0.17-1 +- updated to 1.0.17 final + +* Thu Apr 3 2008 Jim Radford - 1.0.16-3 +- Fix multilib doxygen conflicts + +* Tue Feb 19 2008 Fedora Release Engineering - 1.0.16-2 +- Autorebuild for GCC 4.3 + +* Mon Feb 18 2008 Martin Stransky 1.0.16-1 +- updated to 1.0.16 final + +* Mon Oct 29 2007 Martin Stransky 1.0.15-1 +- updated to 1.0.15 final + +* Wed Oct 17 2007 Lennart Poettering 1.0.15-0.3.rc3 +- Add hook to /etc/alsa/alsa.conf so that /etc/alsa/default-pulse.conf + is loaded when it exists. This allows us to enable the pulse plugin by + default depending on whether it is installed or not. + +* Mon Oct 15 2007 Martin Stransky 1.0.15-0.3.rc3 +- updated to 1.0.15rc3 + +* Thu Sep 20 2007 Matthias Saou 1.0.15-0.2.rc2 +- Update License field. +- Use configdir instead of sysconfdir hacks (cleaner). +- Remove redundant optflags overriding. +- Switch to using main "version", and merge "postver" since this is the right + way of doing things (see NamingGuidelines#NonNumericRelease). +- Remove static library. +- Mark all of /etc/alsa as config, but not "noreplace". +- Remove useless rpath on 64bit archs. + +* Wed Sep 19 2007 Martin Stransky 1.0.15-0.1.rc2 +- updated to 1.0.15rc2 + +* Thu Aug 16 2007 Martin Stransky 1.0.14-3 +- updated to 1.0.14a + +* Wed Aug 15 2007 Lennart Poettering 1.0.14-2 +- fixed #251307 - fix plugindir directory specification +- fix build with newer glibc where open() is a macro + +* Wed Jul 25 2007 Martin Stransky 1.0.14-1 +- bumped release number +- fixed #246011 - alsa-lib should own /usr/lib/alsa-lib/smixer + +* Thu Jun 7 2007 Martin Stransky 1.0.14-0.5 +- new upstream + +* Tue Apr 10 2007 Martin Stransky 1.0.14-0.4.rc3 +- added fix for #233764 - unowned directories + +* Thu Mar 8 2007 Martin Stransky 1.0.14-0.3.rc3 +- new upstream + +* Fri Jan 19 2007 Martin Stransky 1.0.14-0.2.rc2 +- new upstream + +* Mon Dec 11 2006 Martin Stransky 1.0.14-0.1.rc1 +- new upstream + +* Fri Aug 25 2006 Martin Stransky 1.0.12-2 +- new upstream + +* Mon Aug 07 2006 Martin Stransky 1.0.12-1.rc2 +- new upstream + +* Thu Jul 20 2006 Martin Stransky 1.0.12-1.rc1 +- new upstream +- removed ainit (no longer needed in the new upstream) + +* Wed Jul 19 2006 Jesse Keating - 1.0.11-6.rc2 +- fix release for upgrade path + +* Wed Jul 12 2006 Jesse Keating - 1.0.11-3.rc2.2.1 +- rebuild + +* Fri Feb 10 2006 Jesse Keating - 1.0.11-3.rc2.2 +- bump again for double-long bug on ppc(64) + +* Tue Feb 07 2006 Jesse Keating - 1.0.11-3.rc2.1 +- rebuilt for new gcc4.1 snapshot and glibc changes + +* Fri Feb 3 2006 Martin Stransky 1.0.11-3.rc2 +- fix for #179446 - don't remove old SHM memory/keys during login + +* Fri Jan 13 2006 Martin Stransky 1.0.11-2.rc2 +- fix for #169729 - Kernel update makes snd-atiixp-modem & slmodemd fail +- new ainit (0.7) should fix some problems with root users + +* Thu Jan 12 2006 Martin Stransky 1.0.11-1.rc2 +- new upstream version + +* Tue Jan 3 2006 Jesse Keating 1.0.10rf-4 +- rebuilt + +* Fri Dec 9 2005 Martin Stransky 1.0.10rf-3 +- rights for shared memory have been moved to config files + +* Fri Dec 2 2005 Martin Stransky 1.0.10rf-2 +- fix in spec file (#159046) + +* Thu Nov 24 2005 Martin Stransky 1.0.10rf-1 +- new upstream version + +* Tue Sep 27 2005 Martin Stransky 1.0.10rc1-2 +- fixes in config files, new ainit (for #166086) + +* Tue Sep 27 2005 Martin Stransky 1.0.10rc1-1 +- new upstream version + +* Wed Jul 20 2005 Martin Stransky 1.0.9rf-3 +- check for /var/run/console/console.lock (#162982) + +* Thu Jun 16 2005 Martin Stransky 1.0.9rf-2 +- fix for #159411 + +* Mon May 30 2005 Martin Stransky 1.0.9rf-1 +- New upstream version +- moved alsacard utility to alsa-utils + +* Fri May 27 2005 Martin Stransky 1.0.9rc4-2 +- alsacard utility for s-c-s + +* Tue May 24 2005 Bill Nottingham 1.0.9rc4-1 +- update to 1.0.9rc4 (#157180, #158547) + +* Wed May 18 2005 Martin Stransky 1.0.9rc2-5 +- fix for #130593 +- new ainit (dmix/dsnoop is default only for cards which really need it) +- fix dsnoop +- add fix for mixer (from https://bugs.gentoo.org/attachment.cgi?id=58918) + +* Wed May 04 2005 Than Ngo 1.0.9rc2-4 +- apply patch to fix artsd daemon crash #156592 + +* Tue May 3 2005 Martin Stransky 1.0.9rc2-3 +- fixed ainit (#156278, #156505) + +* Thu Apr 28 2005 David Woodhouse 1.0.9rc2-2 +- Fix bogus use of fgetc() in ainit. (#156278) + +* Fri Apr 22 2005 Martin Stransky 1.0.9rc2-1 +- updated to 1.0.9rc2 +- add ainit tool +- dmix is now default pcm device + +* Mon Mar 7 2005 Martin Stransky 1.0.8-4.devel +- gcc4 patch + +* Tue Feb 15 2005 Martin Stransky 1.0.8-3.devel +- add $RPM_OPT_FLAGS to CFLAGS + +* Fri Feb 11 2005 Martin Stransky 1.0.8-2.devel +- add alpha patch (#147388, thx to Sergey Tikhonov) +- fix alsa-mixer on ICH6 system (#146607) + +* Wed Jan 26 2005 Martin Stransky 1.0.8-1.devel +- update to 1.0.8 +- temporarily removed alsa-lib-1.0.7-asym-config.patch + +* Mon Jan 10 2005 Martin Stransky 1.0.7-3.devel +- fix #144518 - stack protection control + +* Sat Jan 08 2005 Colin Walters 1.0.7-2 +- New patch alsa-lib-1.0.7-asym-config.patch, sets up asym + in the default config file and makes it easy to make it + the default via an environment variable. Also increases the + default dmix buffer variables. +- Mark /etc/alsa/alsa.conf as a config file, and use sysconfdir + variable + +* Thu Jan 06 2005 Colin Walters 1.0.7-1 +- New upstream version + +* Tue Nov 30 2004 Bill Nottingham 1.0.6-6 +- fix bad assertion that trips up gstreamer (fixes GNOME bug #159647) +- undef gets in case it's a macro (#141423) + +* Thu Oct 14 2004 Bill Nottingham 1.0.6-3 +- move libraries & data to root fs, needed at boot time + +* Mon Aug 30 2004 Bill Nottingham 1.0.6-1 +- update to 1.0.6 + +* Fri Jul 2 2004 Bill Nottingham 1.0.5-1 +- update to 1.0.5 + +* Tue Jun 15 2004 Elliot Lee +- rebuilt + +* Mon May 17 2004 Colin Walters 1.0.4-1 +- New upstream version + +* Mon May 03 2004 Colin Walters 1.0.3a-2 +- Add patch to avoid assert()ing on errors + +* Thu Mar 11 2004 Bill Nottingham 1.0.3a-1 +- update to 1.0.3a + +* Tue Mar 02 2004 Elliot Lee +- rebuilt + +* Fri Feb 13 2004 Elliot Lee +- rebuilt + +* Wed Jan 28 2004 Bill Nottingham 1.0.2-1 +- update to 1.0.2 + +* Thu Dec 11 2003 Bill Nottingham 1.0.0rc2-1 +- update to 1.0.0rc2 + +* Mon Dec 1 2003 Bill Nottingham 0.9.8-3 +- fix various specfile issues, including License: tag (#111153) + +* Wed Nov 26 2003 Than Ngo 0.9.8-2 +- fixed dependant libraries check on x86_64 + +* Tue Nov 4 2003 Bill Nottingham - 0.9.8-1 +- initial build, modify spec file from Matthias Saou