Commit d1d0b6b6 authored by Christian Vogel's avatar Christian Vogel Committed by Takashi Iwai

ALSA: bebob: Uninitialized id returned by saffirepro_both_clk_src_get

snd_bebob_stream_check_internal_clock() may get an id from
saffirepro_both_clk_src_get (via clk_src->get()) that was uninitialized.

a) make logic in saffirepro_both_clk_src_get explicit
b) test if id used in snd_bebob_stream_check_internal_clock matches array size

[fixed missing signed prefix to *_maps[] by tiwai]
Signed-off-by: default avatarChristian Vogel <vogelchr@vogel.cx>
Reviewed-by: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
Cc: <stable@vger.kernel.org>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent d5432503
...@@ -27,12 +27,14 @@ ...@@ -27,12 +27,14 @@
#define SAFFIRE_CLOCK_SOURCE_INTERNAL 0 #define SAFFIRE_CLOCK_SOURCE_INTERNAL 0
#define SAFFIRE_CLOCK_SOURCE_SPDIF 1 #define SAFFIRE_CLOCK_SOURCE_SPDIF 1
/* '1' is absent, why... */ /* clock sources as returned from register of Saffire Pro 10 and 26 */
#define SAFFIREPRO_CLOCK_SOURCE_INTERNAL 0 #define SAFFIREPRO_CLOCK_SOURCE_INTERNAL 0
#define SAFFIREPRO_CLOCK_SOURCE_SKIP 1 /* never used on hardware */
#define SAFFIREPRO_CLOCK_SOURCE_SPDIF 2 #define SAFFIREPRO_CLOCK_SOURCE_SPDIF 2
#define SAFFIREPRO_CLOCK_SOURCE_ADAT1 3 #define SAFFIREPRO_CLOCK_SOURCE_ADAT1 3 /* not used on s.pro. 10 */
#define SAFFIREPRO_CLOCK_SOURCE_ADAT2 4 #define SAFFIREPRO_CLOCK_SOURCE_ADAT2 4 /* not used on s.pro. 10 */
#define SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK 5 #define SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK 5
#define SAFFIREPRO_CLOCK_SOURCE_COUNT 6
/* S/PDIF, ADAT1, ADAT2 is enabled or not. three quadlets */ /* S/PDIF, ADAT1, ADAT2 is enabled or not. three quadlets */
#define SAFFIREPRO_ENABLE_DIG_IFACES 0x01a4 #define SAFFIREPRO_ENABLE_DIG_IFACES 0x01a4
...@@ -101,13 +103,34 @@ saffire_write_quad(struct snd_bebob *bebob, u64 offset, u32 value) ...@@ -101,13 +103,34 @@ saffire_write_quad(struct snd_bebob *bebob, u64 offset, u32 value)
&data, sizeof(__be32), 0); &data, sizeof(__be32), 0);
} }
static char *const saffirepro_10_clk_src_labels[] = {
SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "Word Clock"
};
static char *const saffirepro_26_clk_src_labels[] = { static char *const saffirepro_26_clk_src_labels[] = {
SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "ADAT1", "ADAT2", "Word Clock" SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "ADAT1", "ADAT2", "Word Clock"
}; };
/* Value maps between registers and labels for SaffirePro 10/26. */
static char *const saffirepro_10_clk_src_labels[] = { static const signed char saffirepro_clk_maps[][SAFFIREPRO_CLOCK_SOURCE_COUNT] = {
SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "Word Clock" /* SaffirePro 10 */
[0] = {
[SAFFIREPRO_CLOCK_SOURCE_INTERNAL] = 0,
[SAFFIREPRO_CLOCK_SOURCE_SKIP] = -1, /* not supported */
[SAFFIREPRO_CLOCK_SOURCE_SPDIF] = 1,
[SAFFIREPRO_CLOCK_SOURCE_ADAT1] = -1, /* not supported */
[SAFFIREPRO_CLOCK_SOURCE_ADAT2] = -1, /* not supported */
[SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK] = 2,
},
/* SaffirePro 26 */
[1] = {
[SAFFIREPRO_CLOCK_SOURCE_INTERNAL] = 0,
[SAFFIREPRO_CLOCK_SOURCE_SKIP] = -1, /* not supported */
[SAFFIREPRO_CLOCK_SOURCE_SPDIF] = 1,
[SAFFIREPRO_CLOCK_SOURCE_ADAT1] = 2,
[SAFFIREPRO_CLOCK_SOURCE_ADAT2] = 3,
[SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK] = 4,
}
}; };
static int static int
saffirepro_both_clk_freq_get(struct snd_bebob *bebob, unsigned int *rate) saffirepro_both_clk_freq_get(struct snd_bebob *bebob, unsigned int *rate)
{ {
...@@ -138,24 +161,35 @@ saffirepro_both_clk_freq_set(struct snd_bebob *bebob, unsigned int rate) ...@@ -138,24 +161,35 @@ saffirepro_both_clk_freq_set(struct snd_bebob *bebob, unsigned int rate)
return saffire_write_quad(bebob, SAFFIREPRO_RATE_NOREBOOT, id); return saffire_write_quad(bebob, SAFFIREPRO_RATE_NOREBOOT, id);
} }
/*
* query hardware for current clock source, return our internally
* used clock index in *id, depending on hardware.
*/
static int static int
saffirepro_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id) saffirepro_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id)
{ {
int err; int err;
u32 value; u32 value; /* clock source read from hw register */
const signed char *map;
err = saffire_read_quad(bebob, SAFFIREPRO_OFFSET_CLOCK_SOURCE, &value); err = saffire_read_quad(bebob, SAFFIREPRO_OFFSET_CLOCK_SOURCE, &value);
if (err < 0) if (err < 0)
goto end; goto end;
if (bebob->spec->clock->labels == saffirepro_10_clk_src_labels) { /* depending on hardware, use a different mapping */
if (value == SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK) if (bebob->spec->clock->labels == saffirepro_10_clk_src_labels)
*id = 2; map = saffirepro_clk_maps[0];
else if (value == SAFFIREPRO_CLOCK_SOURCE_SPDIF) else
*id = 1; map = saffirepro_clk_maps[1];
} else if (value > 1) {
*id = value - 1; /* In a case that this driver cannot handle the value of register. */
if (value >= SAFFIREPRO_CLOCK_SOURCE_COUNT || map[value] < 0) {
err = -EIO;
goto end;
} }
*id = (unsigned int)map[value];
end: end:
return err; return err;
} }
......
...@@ -129,12 +129,24 @@ snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal) ...@@ -129,12 +129,24 @@ snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal)
/* 1.The device has its own operation to switch source of clock */ /* 1.The device has its own operation to switch source of clock */
if (clk_spec) { if (clk_spec) {
err = clk_spec->get(bebob, &id); err = clk_spec->get(bebob, &id);
if (err < 0) if (err < 0) {
dev_err(&bebob->unit->device, dev_err(&bebob->unit->device,
"fail to get clock source: %d\n", err); "fail to get clock source: %d\n", err);
else if (strncmp(clk_spec->labels[id], SND_BEBOB_CLOCK_INTERNAL, goto end;
}
if (id >= clk_spec->num) {
dev_err(&bebob->unit->device,
"clock source %d out of range 0..%d\n",
id, clk_spec->num - 1);
err = -EIO;
goto end;
}
if (strncmp(clk_spec->labels[id], SND_BEBOB_CLOCK_INTERNAL,
strlen(SND_BEBOB_CLOCK_INTERNAL)) == 0) strlen(SND_BEBOB_CLOCK_INTERNAL)) == 0)
*internal = true; *internal = true;
goto end; goto end;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment