diff options
author | Eldad Zack <eldad@fogrefinery.com> | 2013-04-03 17:18:54 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-04-04 02:30:59 -0400 |
commit | 06ffc1ebddbed88662a47646ff6aa6a2b41f0aec (patch) | |
tree | 7090ac76f3cb113cc077090375162ab9765a35a5 /sound/usb | |
parent | f6a8bc70f85fdc49c5a3eca687c6018ffee8f050 (diff) |
ALSA: usb-audio: UAC2: do clock validity check earlier
Move the check that parse_audio_format_rates_v2() do after
receiving the clock source entity ID directly into the find
function and add a validation flag to the function.
This patch does not introduce any logic flow change.
It is provided to allow introducing automatic clock switching
easier later. By moving this uac_clock_source_is_valid callsite,
2 additional callsites can be avoided.
Signed-off-by: Eldad Zack <eldad@fogrefinery.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb')
-rw-r--r-- | sound/usb/clock.c | 34 | ||||
-rw-r--r-- | sound/usb/clock.h | 3 | ||||
-rw-r--r-- | sound/usb/format.c | 2 |
3 files changed, 21 insertions, 18 deletions
diff --git a/sound/usb/clock.c b/sound/usb/clock.c index 013b346f045d..0c98f52a1c9c 100644 --- a/sound/usb/clock.c +++ b/sound/usb/clock.c | |||
@@ -131,7 +131,8 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id) | |||
131 | } | 131 | } |
132 | 132 | ||
133 | static int __uac_clock_find_source(struct snd_usb_audio *chip, | 133 | static int __uac_clock_find_source(struct snd_usb_audio *chip, |
134 | int entity_id, unsigned long *visited) | 134 | int entity_id, unsigned long *visited, |
135 | bool validate) | ||
135 | { | 136 | { |
136 | struct uac_clock_source_descriptor *source; | 137 | struct uac_clock_source_descriptor *source; |
137 | struct uac_clock_selector_descriptor *selector; | 138 | struct uac_clock_selector_descriptor *selector; |
@@ -148,8 +149,15 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, | |||
148 | 149 | ||
149 | /* first, see if the ID we're looking for is a clock source already */ | 150 | /* first, see if the ID we're looking for is a clock source already */ |
150 | source = snd_usb_find_clock_source(chip->ctrl_intf, entity_id); | 151 | source = snd_usb_find_clock_source(chip->ctrl_intf, entity_id); |
151 | if (source) | 152 | if (source) { |
152 | return source->bClockID; | 153 | entity_id = source->bClockID; |
154 | if (validate && !uac_clock_source_is_valid(chip, entity_id)) { | ||
155 | snd_printk(KERN_ERR "usb-audio:%d: clock source %d is not valid, cannot use\n", | ||
156 | chip->dev->devnum, entity_id); | ||
157 | return -ENXIO; | ||
158 | } | ||
159 | return entity_id; | ||
160 | } | ||
153 | 161 | ||
154 | selector = snd_usb_find_clock_selector(chip->ctrl_intf, entity_id); | 162 | selector = snd_usb_find_clock_selector(chip->ctrl_intf, entity_id); |
155 | if (selector) { | 163 | if (selector) { |
@@ -164,7 +172,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, | |||
164 | /* Selector values are one-based */ | 172 | /* Selector values are one-based */ |
165 | 173 | ||
166 | if (ret > selector->bNrInPins || ret < 1) { | 174 | if (ret > selector->bNrInPins || ret < 1) { |
167 | printk(KERN_ERR | 175 | snd_printk(KERN_ERR |
168 | "%s(): selector reported illegal value, id %d, ret %d\n", | 176 | "%s(): selector reported illegal value, id %d, ret %d\n", |
169 | __func__, selector->bClockID, ret); | 177 | __func__, selector->bClockID, ret); |
170 | 178 | ||
@@ -172,14 +180,14 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, | |||
172 | } | 180 | } |
173 | 181 | ||
174 | return __uac_clock_find_source(chip, selector->baCSourceID[ret-1], | 182 | return __uac_clock_find_source(chip, selector->baCSourceID[ret-1], |
175 | visited); | 183 | visited, validate); |
176 | } | 184 | } |
177 | 185 | ||
178 | /* FIXME: multipliers only act as pass-thru element for now */ | 186 | /* FIXME: multipliers only act as pass-thru element for now */ |
179 | multiplier = snd_usb_find_clock_multiplier(chip->ctrl_intf, entity_id); | 187 | multiplier = snd_usb_find_clock_multiplier(chip->ctrl_intf, entity_id); |
180 | if (multiplier) | 188 | if (multiplier) |
181 | return __uac_clock_find_source(chip, multiplier->bCSourceID, | 189 | return __uac_clock_find_source(chip, multiplier->bCSourceID, |
182 | visited); | 190 | visited, validate); |
183 | 191 | ||
184 | return -EINVAL; | 192 | return -EINVAL; |
185 | } | 193 | } |
@@ -195,11 +203,12 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, | |||
195 | * | 203 | * |
196 | * Returns the clock source UnitID (>=0) on success, or an error. | 204 | * Returns the clock source UnitID (>=0) on success, or an error. |
197 | */ | 205 | */ |
198 | int snd_usb_clock_find_source(struct snd_usb_audio *chip, int entity_id) | 206 | int snd_usb_clock_find_source(struct snd_usb_audio *chip, int entity_id, |
207 | bool validate) | ||
199 | { | 208 | { |
200 | DECLARE_BITMAP(visited, 256); | 209 | DECLARE_BITMAP(visited, 256); |
201 | memset(visited, 0, sizeof(visited)); | 210 | memset(visited, 0, sizeof(visited)); |
202 | return __uac_clock_find_source(chip, entity_id, visited); | 211 | return __uac_clock_find_source(chip, entity_id, visited, validate); |
203 | } | 212 | } |
204 | 213 | ||
205 | static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface, | 214 | static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface, |
@@ -275,18 +284,11 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface, | |||
275 | struct usb_device *dev = chip->dev; | 284 | struct usb_device *dev = chip->dev; |
276 | __le32 data; | 285 | __le32 data; |
277 | int err, cur_rate, prev_rate; | 286 | int err, cur_rate, prev_rate; |
278 | int clock = snd_usb_clock_find_source(chip, fmt->clock); | 287 | int clock = snd_usb_clock_find_source(chip, fmt->clock, true); |
279 | 288 | ||
280 | if (clock < 0) | 289 | if (clock < 0) |
281 | return clock; | 290 | return clock; |
282 | 291 | ||
283 | if (!uac_clock_source_is_valid(chip, clock)) { | ||
284 | /* TODO: should we try to find valid clock setups by ourself? */ | ||
285 | snd_printk(KERN_ERR "%d:%d:%d: clock source %d is not valid, cannot use\n", | ||
286 | dev->devnum, iface, fmt->altsetting, clock); | ||
287 | return -ENXIO; | ||
288 | } | ||
289 | |||
290 | prev_rate = get_sample_rate_v2(chip, iface, fmt->altsetting, clock); | 292 | prev_rate = get_sample_rate_v2(chip, iface, fmt->altsetting, clock); |
291 | 293 | ||
292 | data = cpu_to_le32(rate); | 294 | data = cpu_to_le32(rate); |
diff --git a/sound/usb/clock.h b/sound/usb/clock.h index 46630936d31f..d592e4a29856 100644 --- a/sound/usb/clock.h +++ b/sound/usb/clock.h | |||
@@ -5,6 +5,7 @@ int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface, | |||
5 | struct usb_host_interface *alts, | 5 | struct usb_host_interface *alts, |
6 | struct audioformat *fmt, int rate); | 6 | struct audioformat *fmt, int rate); |
7 | 7 | ||
8 | int snd_usb_clock_find_source(struct snd_usb_audio *chip, int entity_id); | 8 | int snd_usb_clock_find_source(struct snd_usb_audio *chip, int entity_id, |
9 | bool validate); | ||
9 | 10 | ||
10 | #endif /* __USBAUDIO_CLOCK_H */ | 11 | #endif /* __USBAUDIO_CLOCK_H */ |
diff --git a/sound/usb/format.c b/sound/usb/format.c index a695cafc0599..20c775170959 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c | |||
@@ -280,7 +280,7 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip, | |||
280 | struct usb_device *dev = chip->dev; | 280 | struct usb_device *dev = chip->dev; |
281 | unsigned char tmp[2], *data; | 281 | unsigned char tmp[2], *data; |
282 | int nr_triplets, data_size, ret = 0; | 282 | int nr_triplets, data_size, ret = 0; |
283 | int clock = snd_usb_clock_find_source(chip, fp->clock); | 283 | int clock = snd_usb_clock_find_source(chip, fp->clock, false); |
284 | 284 | ||
285 | if (clock < 0) { | 285 | if (clock < 0) { |
286 | snd_printk(KERN_ERR "%s(): unable to find clock source (clock %d)\n", | 286 | snd_printk(KERN_ERR "%s(): unable to find clock source (clock %d)\n", |