diff options
| author | Christian Vogel <vogelchr@vogel.cx> | 2014-10-25 07:40:41 -0400 |
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2014-10-27 09:09:14 -0400 |
| commit | d1d0b6b668818571122d30d68a0b3f768bd83a52 (patch) | |
| tree | 9b7d31a99e386ee272992e9f0fd7b67c5dd64316 /sound/firewire/bebob | |
| parent | d5432503bfb49f3425bad0b850714ffd8b533cfc (diff) | |
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: Christian Vogel <vogelchr@vogel.cx>
Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Cc: <stable@vger.kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/firewire/bebob')
| -rw-r--r-- | sound/firewire/bebob/bebob_focusrite.c | 62 | ||||
| -rw-r--r-- | sound/firewire/bebob/bebob_stream.c | 18 |
2 files changed, 63 insertions, 17 deletions
diff --git a/sound/firewire/bebob/bebob_focusrite.c b/sound/firewire/bebob/bebob_focusrite.c index 45a0eed6d5b1..3b052ed0fbf5 100644 --- a/sound/firewire/bebob/bebob_focusrite.c +++ b/sound/firewire/bebob/bebob_focusrite.c | |||
| @@ -27,12 +27,14 @@ | |||
| 27 | #define SAFFIRE_CLOCK_SOURCE_INTERNAL 0 | 27 | #define SAFFIRE_CLOCK_SOURCE_INTERNAL 0 |
| 28 | #define SAFFIRE_CLOCK_SOURCE_SPDIF 1 | 28 | #define SAFFIRE_CLOCK_SOURCE_SPDIF 1 |
| 29 | 29 | ||
| 30 | /* '1' is absent, why... */ | 30 | /* clock sources as returned from register of Saffire Pro 10 and 26 */ |
| 31 | #define SAFFIREPRO_CLOCK_SOURCE_INTERNAL 0 | 31 | #define SAFFIREPRO_CLOCK_SOURCE_INTERNAL 0 |
| 32 | #define SAFFIREPRO_CLOCK_SOURCE_SKIP 1 /* never used on hardware */ | ||
| 32 | #define SAFFIREPRO_CLOCK_SOURCE_SPDIF 2 | 33 | #define SAFFIREPRO_CLOCK_SOURCE_SPDIF 2 |
| 33 | #define SAFFIREPRO_CLOCK_SOURCE_ADAT1 3 | 34 | #define SAFFIREPRO_CLOCK_SOURCE_ADAT1 3 /* not used on s.pro. 10 */ |
| 34 | #define SAFFIREPRO_CLOCK_SOURCE_ADAT2 4 | 35 | #define SAFFIREPRO_CLOCK_SOURCE_ADAT2 4 /* not used on s.pro. 10 */ |
| 35 | #define SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK 5 | 36 | #define SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK 5 |
| 37 | #define SAFFIREPRO_CLOCK_SOURCE_COUNT 6 | ||
| 36 | 38 | ||
| 37 | /* S/PDIF, ADAT1, ADAT2 is enabled or not. three quadlets */ | 39 | /* S/PDIF, ADAT1, ADAT2 is enabled or not. three quadlets */ |
| 38 | #define SAFFIREPRO_ENABLE_DIG_IFACES 0x01a4 | 40 | #define SAFFIREPRO_ENABLE_DIG_IFACES 0x01a4 |
| @@ -101,13 +103,34 @@ saffire_write_quad(struct snd_bebob *bebob, u64 offset, u32 value) | |||
| 101 | &data, sizeof(__be32), 0); | 103 | &data, sizeof(__be32), 0); |
| 102 | } | 104 | } |
| 103 | 105 | ||
| 106 | static char *const saffirepro_10_clk_src_labels[] = { | ||
| 107 | SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "Word Clock" | ||
| 108 | }; | ||
| 104 | static char *const saffirepro_26_clk_src_labels[] = { | 109 | static char *const saffirepro_26_clk_src_labels[] = { |
| 105 | SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "ADAT1", "ADAT2", "Word Clock" | 110 | SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "ADAT1", "ADAT2", "Word Clock" |
| 106 | }; | 111 | }; |
| 107 | 112 | /* Value maps between registers and labels for SaffirePro 10/26. */ | |
| 108 | static char *const saffirepro_10_clk_src_labels[] = { | 113 | static const signed char saffirepro_clk_maps[][SAFFIREPRO_CLOCK_SOURCE_COUNT] = { |
| 109 | SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "Word Clock" | 114 | /* SaffirePro 10 */ |
| 115 | [0] = { | ||
| 116 | [SAFFIREPRO_CLOCK_SOURCE_INTERNAL] = 0, | ||
| 117 | [SAFFIREPRO_CLOCK_SOURCE_SKIP] = -1, /* not supported */ | ||
| 118 | [SAFFIREPRO_CLOCK_SOURCE_SPDIF] = 1, | ||
| 119 | [SAFFIREPRO_CLOCK_SOURCE_ADAT1] = -1, /* not supported */ | ||
| 120 | [SAFFIREPRO_CLOCK_SOURCE_ADAT2] = -1, /* not supported */ | ||
| 121 | [SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK] = 2, | ||
| 122 | }, | ||
| 123 | /* SaffirePro 26 */ | ||
| 124 | [1] = { | ||
| 125 | [SAFFIREPRO_CLOCK_SOURCE_INTERNAL] = 0, | ||
| 126 | [SAFFIREPRO_CLOCK_SOURCE_SKIP] = -1, /* not supported */ | ||
| 127 | [SAFFIREPRO_CLOCK_SOURCE_SPDIF] = 1, | ||
| 128 | [SAFFIREPRO_CLOCK_SOURCE_ADAT1] = 2, | ||
| 129 | [SAFFIREPRO_CLOCK_SOURCE_ADAT2] = 3, | ||
| 130 | [SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK] = 4, | ||
| 131 | } | ||
| 110 | }; | 132 | }; |
| 133 | |||
| 111 | static int | 134 | static int |
| 112 | saffirepro_both_clk_freq_get(struct snd_bebob *bebob, unsigned int *rate) | 135 | saffirepro_both_clk_freq_get(struct snd_bebob *bebob, unsigned int *rate) |
| 113 | { | 136 | { |
| @@ -138,24 +161,35 @@ saffirepro_both_clk_freq_set(struct snd_bebob *bebob, unsigned int rate) | |||
| 138 | 161 | ||
| 139 | return saffire_write_quad(bebob, SAFFIREPRO_RATE_NOREBOOT, id); | 162 | return saffire_write_quad(bebob, SAFFIREPRO_RATE_NOREBOOT, id); |
| 140 | } | 163 | } |
| 164 | |||
| 165 | /* | ||
| 166 | * query hardware for current clock source, return our internally | ||
| 167 | * used clock index in *id, depending on hardware. | ||
| 168 | */ | ||
| 141 | static int | 169 | static int |
| 142 | saffirepro_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id) | 170 | saffirepro_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id) |
| 143 | { | 171 | { |
| 144 | int err; | 172 | int err; |
| 145 | u32 value; | 173 | u32 value; /* clock source read from hw register */ |
| 174 | const signed char *map; | ||
| 146 | 175 | ||
| 147 | err = saffire_read_quad(bebob, SAFFIREPRO_OFFSET_CLOCK_SOURCE, &value); | 176 | err = saffire_read_quad(bebob, SAFFIREPRO_OFFSET_CLOCK_SOURCE, &value); |
| 148 | if (err < 0) | 177 | if (err < 0) |
| 149 | goto end; | 178 | goto end; |
| 150 | 179 | ||
| 151 | if (bebob->spec->clock->labels == saffirepro_10_clk_src_labels) { | 180 | /* depending on hardware, use a different mapping */ |
| 152 | if (value == SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK) | 181 | if (bebob->spec->clock->labels == saffirepro_10_clk_src_labels) |
| 153 | *id = 2; | 182 | map = saffirepro_clk_maps[0]; |
| 154 | else if (value == SAFFIREPRO_CLOCK_SOURCE_SPDIF) | 183 | else |
| 155 | *id = 1; | 184 | map = saffirepro_clk_maps[1]; |
| 156 | } else if (value > 1) { | 185 | |
| 157 | *id = value - 1; | 186 | /* In a case that this driver cannot handle the value of register. */ |
| 187 | if (value >= SAFFIREPRO_CLOCK_SOURCE_COUNT || map[value] < 0) { | ||
| 188 | err = -EIO; | ||
| 189 | goto end; | ||
| 158 | } | 190 | } |
| 191 | |||
| 192 | *id = (unsigned int)map[value]; | ||
| 159 | end: | 193 | end: |
| 160 | return err; | 194 | return err; |
| 161 | } | 195 | } |
diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index ef4d0c9f6578..1aab0a32870c 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c | |||
| @@ -129,12 +129,24 @@ snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal) | |||
| 129 | /* 1.The device has its own operation to switch source of clock */ | 129 | /* 1.The device has its own operation to switch source of clock */ |
| 130 | if (clk_spec) { | 130 | if (clk_spec) { |
| 131 | err = clk_spec->get(bebob, &id); | 131 | err = clk_spec->get(bebob, &id); |
| 132 | if (err < 0) | 132 | if (err < 0) { |
| 133 | dev_err(&bebob->unit->device, | 133 | dev_err(&bebob->unit->device, |
| 134 | "fail to get clock source: %d\n", err); | 134 | "fail to get clock source: %d\n", err); |
| 135 | else if (strncmp(clk_spec->labels[id], SND_BEBOB_CLOCK_INTERNAL, | 135 | goto end; |
| 136 | strlen(SND_BEBOB_CLOCK_INTERNAL)) == 0) | 136 | } |
| 137 | |||
| 138 | if (id >= clk_spec->num) { | ||
| 139 | dev_err(&bebob->unit->device, | ||
| 140 | "clock source %d out of range 0..%d\n", | ||
| 141 | id, clk_spec->num - 1); | ||
| 142 | err = -EIO; | ||
| 143 | goto end; | ||
| 144 | } | ||
| 145 | |||
| 146 | if (strncmp(clk_spec->labels[id], SND_BEBOB_CLOCK_INTERNAL, | ||
| 147 | strlen(SND_BEBOB_CLOCK_INTERNAL)) == 0) | ||
| 137 | *internal = true; | 148 | *internal = true; |
| 149 | |||
| 138 | goto end; | 150 | goto end; |
| 139 | } | 151 | } |
| 140 | 152 | ||
