[alsa-devel] ascenario: Last batch of fixes.
Hello.
This is the last set of fixes I have in my queue.
[PATCH 1/3] ascenario: Add check for set scenario in snd_scenario_get_control_id() Debugged some hours that I should test it after _set() and not only after _list(). Better let the user know that no scenario is set instead of silently using a non existing scenario and fail.
[PATCH 2/3] ascenario: Convert last sprintf() to snprintf() Some more sprintf() replaced with the more secure snprintf().
[PATCH 3/3] ascenario: Make sequences unique for every scenario. That one actually got me some grey hairs. I'm pretty sure I tested it earlier and it worked as it should, but I can find now traces of this. Fixed for good now.
[PATCH] ascenario: Add dump and configure utils for ascneario. Reference patch against alsa-utils for some small utilities using the new scenario API. Only change from the last time is that _dump() now has two parameters even if the new one is still unused.
regards Stefan Schmidt
From: Stefan Schmidt stefan@slimlogic.co.uk
Without this check we may have the situation that scn->current_scenario == scn->num_scenarios and then we get our values from a wrong memory area. Could happen if you use the function directly after snd_scenario_list()
Also use short instead of int for the numids.
Signed-off-by: Stefan Schmidt stefan@slimlogic.co.uk --- src/ascenario.c | 8 +++++++- 1 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/src/ascenario.c b/src/ascenario.c index 11912ab..d2a9519 100644 --- a/src/ascenario.c +++ b/src/ascenario.c @@ -1349,7 +1349,8 @@ int snd_scenario_get_integer(snd_scenario_t *scn, int type, int *value) int snd_scenario_get_control_id(snd_scenario_t *scn, int type, snd_ctl_elem_id_t *id) { - int numid, ret, i, count, tmp; + short numid, tmp; + int ret, i, count; snd_ctl_t *handle; snd_ctl_card_info_t *info; snd_ctl_elem_list_t *list; @@ -1357,6 +1358,11 @@ int snd_scenario_get_control_id(snd_scenario_t *scn, int type, snd_ctl_card_info_alloca(&info); snd_ctl_elem_list_alloca(&list);
+ if (scn->current_scenario >= scn->num_scenarios) { + scn_error("%s: No scenario set.\n", __func__); + return -EINVAL; + } + switch (type) { case SND_SCN_KCTL_MASTER_PLAYBACK_VOLUME: numid = scn->scenario[scn->current_scenario].playback_volume_id;
From: Stefan Schmidt stefan@slimlogic.co.uk
Signed-off-by: Stefan Schmidt stefan@slimlogic.co.uk --- src/ascenario.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/ascenario.c b/src/ascenario.c index d2a9519..49845dc 100644 --- a/src/ascenario.c +++ b/src/ascenario.c @@ -554,11 +554,11 @@ static int read_sequence_file(snd_scenario_t *scn, int position) struct scenario_info *info = &scn->scenario[scn->current_scenario];
if (position == PRE_SEQ) { - sprintf(filename, "%s/%s/%s", ALSA_SCN_DIR, scn->card_name, + snprintf(filename, MAX_FILE, "%s/%s/%s", ALSA_SCN_DIR, scn->card_name, info->pre_sequence_file); } else { - sprintf(filename, "%s/%s/%s", ALSA_SCN_DIR, scn->card_name, + snprintf(filename, MAX_FILE, "%s/%s/%s", ALSA_SCN_DIR, scn->card_name, info->post_sequence_file); }
@@ -777,7 +777,7 @@ static int import_master_config(snd_scenario_t *scn) FILE *f; char filename[MAX_FILE];
- sprintf(filename, "%s/%s.conf", ALSA_SCN_DIR, scn->card_name); + snprintf(filename, MAX_FILE, "%s/%s.conf", ALSA_SCN_DIR, scn->card_name);
fd = open(filename, O_RDONLY | O_NOATIME); if (fd < 0) {
From: Stefan Schmidt stefan@slimlogic.co.uk
I could have sworn that worked before. Anyway, pre and post sequences are now unique per scenario as they always should have been.
Signed-off-by: Stefan Schmidt stefan@slimlogic.co.uk --- src/ascenario.c | 40 ++++++++++++++++++++++------------------ 1 files changed, 22 insertions(+), 18 deletions(-)
diff --git a/src/ascenario.c b/src/ascenario.c index 49845dc..945b776 100644 --- a/src/ascenario.c +++ b/src/ascenario.c @@ -71,6 +71,8 @@ struct scenario_info { char *file; char *pre_sequence_file; char *post_sequence_file; + struct sequence_element *pre_seq_list; /* Linked list for pre sequence */ + struct sequence_element *post_seq_list; /* Linked list for post sequence */ short playback_volume_id; short playback_switch_id; short capture_volume_id; @@ -85,8 +87,6 @@ struct snd_scenario { int current_scenario; int num_scenarios; /* number of supported scenarios */ int num_kcontrols; /* number of kcontrols */ - struct sequence_element *pre_seq_list; /* Linked list for pre sequence */ - struct sequence_element *post_seq_list; /* Linked list for post sequence */ const char **list; struct scenario_info *scenario; /* var len array of scenario info */ struct control_settings *control; /* var len array of controls */ @@ -414,11 +414,11 @@ static void seq_list_append(snd_scenario_t *scn, struct sequence_element *last, *tmp;
if (position) { - if (!scn->post_seq_list) - scn->post_seq_list = curr; + if (!scn->scenario[scn->current_scenario].post_seq_list) + scn->scenario[scn->current_scenario].post_seq_list = curr;
else { - tmp = scn->post_seq_list; + tmp = scn->scenario[scn->current_scenario].post_seq_list; while (tmp) { last = tmp; tmp = tmp->next; @@ -427,11 +427,11 @@ static void seq_list_append(snd_scenario_t *scn, } } else { - if (!scn->pre_seq_list) { - scn->pre_seq_list = curr; + if (!scn->scenario[scn->current_scenario].pre_seq_list) { + scn->scenario[scn->current_scenario].pre_seq_list = curr; } else { - tmp = scn->pre_seq_list; + tmp = scn->scenario[scn->current_scenario].pre_seq_list; while (tmp) { last = tmp; tmp = tmp->next; @@ -595,10 +595,12 @@ static int parse_scenario(snd_scenario_t *scn, FILE *f, int line_) bzero(scn->scenario + offset, len); info = scn->scenario + scn->num_scenarios;
- /* Set sequence filename to NULL as it is optional and we want to check - * for NULL to avoid segfaults */ + /* Set to NULL as it is optional and we want to check for NULL to + * avoid segfaults */ info->pre_sequence_file = NULL; info->post_sequence_file = NULL; + info->pre_seq_list = NULL; + info->post_seq_list = NULL;
while(fgets(buf, MAX_BUF, f) != NULL) {
@@ -953,10 +955,6 @@ static void free_scn(snd_scenario_t *scn) free(scn->list); if (scn->card_name) free(scn->card_name); - if (scn->pre_seq_list) - free(scn->pre_seq_list); - if (scn->post_seq_list) - free(scn->post_seq_list);
if (scn->scenario) { for (i = 0; i < scn->num_scenarios; i++) { @@ -970,6 +968,10 @@ static void free_scn(snd_scenario_t *scn) free(info->pre_sequence_file); if (info->post_sequence_file) free(info->post_sequence_file); + if (info->pre_seq_list) + free(info->pre_seq_list); + if (info->post_seq_list) + free(info->post_seq_list); } free(scn->scenario); } @@ -1216,8 +1218,9 @@ found:
/* If we have a sequence list that should be executed before the new * scenario is set do it now */ - if (scn->pre_seq_list) - exec_sequence(scn->pre_seq_list, scn, list, handle); + if (scn->scenario[scn->current_scenario].pre_seq_list) + exec_sequence(scn->scenario[scn->current_scenario].pre_seq_list, + scn, list, handle);
/* iterate through each kcontrol and add to db */ for (i = 0; i < count; ++i) { @@ -1234,8 +1237,9 @@ found:
/* If we have a sequence list that should be executed after the new * scenario is set do it now */ - if (scn->post_seq_list) - exec_sequence(scn->post_seq_list, scn, list, handle); + if (scn->scenario[scn->current_scenario].post_seq_list) + exec_sequence(scn->scenario[scn->current_scenario].post_seq_list, + scn, list, handle);
free: snd_ctl_elem_list_free_space(list);
From: Stefan Schmidt stefan@slimlogic.co.uk
ascndump is used to dump the kcontrols in a syntax that can be used with ascnctl later. To list and set scenarios you can use ascnctl. This patch depends on the ascenario infrstructure to be merged in alsa-lib.
CC: Ian Molton ian@mnementh.co.uk CC: Graeme Gregory gg@slimlogic.co.uk Signed-off-by: Liam Girdwood lrg@slimlogic.co.uk Signed-off-by: Stefan Schmidt stefan@slimlogic.co.uk --- Makefile.am | 2 +- ascenario/Makefile.am | 14 ++++++++ ascenario/alsa-scn.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++ ascenario/dump.c | 34 +++++++++++++++++++ configure.in | 1 + 5 files changed, 139 insertions(+), 1 deletions(-) create mode 100644 ascenario/Makefile.am create mode 100644 ascenario/alsa-scn.c create mode 100644 ascenario/dump.c
diff --git a/Makefile.am b/Makefile.am index 5296977..34c542f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ INCLUDES=-I$(top_srcdir)/include
-SUBDIRS = include alsactl utils m4 po +SUBDIRS = include alsactl ascenario utils m4 po if ALSAMIXER SUBDIRS += alsamixer endif diff --git a/ascenario/Makefile.am b/ascenario/Makefile.am new file mode 100644 index 0000000..88f5a67 --- /dev/null +++ b/ascenario/Makefile.am @@ -0,0 +1,14 @@ +noinst_PROGRAMS = \ + ascnctl \ + ascndump + +ascndump_SOURCES = dump.c + +ascnctl_SOURCES = alsa-scn.c + +INCLUDES = \ + -Wall -I$(top_srcdir)/include + +ascndump_LDADD = -lasound + +ascnctl_LDADD = -lasound diff --git a/ascenario/alsa-scn.c b/ascenario/alsa-scn.c new file mode 100644 index 0000000..1610936 --- /dev/null +++ b/ascenario/alsa-scn.c @@ -0,0 +1,89 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) 2008-2009 SlimLogic Ltd + * Authors: Liam Girdwood lrg@slimlogic.co.uk + * Stefan Schmidt stefan@slimlogic.co.uk + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <alsa/asoundlib.h> +#include <alsa/ascenario.h> + +#define OP_LIST 1 +#define OP_SET 2 + +void print_usage(char *name) { + printf("Usage: %s <cmd> [<scenario>]\n" + " list - list available scenarios\n" + " set <name> - apply scenario <name>\n\n", name); +} + +int main(int argc, char *argv[]) +{ + struct snd_scenario *scn; + int num, i, op = 0, err, ret = 0; + const char **list; + + if(argc > 2) { + if(!strcmp(argv[1], "set")) + op = OP_SET; + } else if(argc > 1) { + if(!strcmp(argv[1], "list")) + op = OP_LIST; + } + + if(!op) { + print_usage(argv[0]); + exit(1); + } + + /* open library */ + scn = snd_scenario_open("default"); + if (scn == NULL) { + printf("%s: failed to init\n", argv[0]); + return 0; + } + + switch (op) { + case OP_LIST: + /* get list of scenarios */ + num = snd_scenario_list(scn, &list); + if (num) { + for(i = 0 ; i < num ; i++) + printf("%s\n", list[i]); + } else { + printf("%s: no scenarios\n", argv[0]); + ret = 2; + } + break; + case OP_SET: + err = snd_scenario_set_scn(scn, argv[2]); + if (err < 0) { + printf("failed to set scenario: %s\n", argv[2]); + ret = 3; + } + break; + default: + print_usage(argv[0]); + break; + } + + snd_scenario_close(scn); + return ret; +} diff --git a/ascenario/dump.c b/ascenario/dump.c new file mode 100644 index 0000000..420db5a --- /dev/null +++ b/ascenario/dump.c @@ -0,0 +1,34 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) 2008-2009 SlimLogic Ltd + * Authors: Liam Girdwood lrg@slimlogic.co.uk + * Stefan Schmidt stefan@slimlogic.co.uk + */ + +#include <stdio.h> +#include <alsa/asoundlib.h> +#include <alsa/ascenario.h> + +int main(int argc, char *argv[]) +{ + if (argc != 2) { + printf("usage: %s card (hw: prefix needed" + " e.g. hw:CARD=0 or hw:Intel)\n", argv[0]); + return 0; + } + + return snd_scenario_dump(NULL, argv[1]); +} diff --git a/configure.in b/configure.in index 931d034..8fcf1d3 100644 --- a/configure.in +++ b/configure.in @@ -270,6 +270,7 @@ AC_OUTPUT(Makefile alsactl/Makefile alsactl/init/Makefile \ m4/Makefile po/Makefile.in \ alsaconf/alsaconf alsaconf/Makefile \ alsaconf/po/Makefile \ + ascenario/Makefile \ aplay/Makefile include/Makefile iecset/Makefile utils/Makefile \ utils/alsa-utils.spec seq/Makefile seq/aconnect/Makefile \ seq/aplaymidi/Makefile seq/aseqdump/Makefile seq/aseqnet/Makefile \
participants (1)
-
Stefan Schmidt