|
@@ -261,19 +261,6 @@ static void stop_endpoints(struct snd_usb_substream *subs,
|
|
force, can_sleep, wait);
|
|
force, can_sleep, wait);
|
|
}
|
|
}
|
|
|
|
|
|
-static int activate_endpoints(struct snd_usb_substream *subs)
|
|
|
|
-{
|
|
|
|
- if (subs->sync_endpoint) {
|
|
|
|
- int ret;
|
|
|
|
-
|
|
|
|
- ret = snd_usb_endpoint_activate(subs->sync_endpoint);
|
|
|
|
- if (ret < 0)
|
|
|
|
- return ret;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return snd_usb_endpoint_activate(subs->data_endpoint);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static int deactivate_endpoints(struct snd_usb_substream *subs)
|
|
static int deactivate_endpoints(struct snd_usb_substream *subs)
|
|
{
|
|
{
|
|
int reta, retb;
|
|
int reta, retb;
|
|
@@ -314,6 +301,33 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
|
|
if (fmt == subs->cur_audiofmt)
|
|
if (fmt == subs->cur_audiofmt)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
|
|
+ /* close the old interface */
|
|
|
|
+ if (subs->interface >= 0 && subs->interface != fmt->iface) {
|
|
|
|
+ err = usb_set_interface(subs->dev, subs->interface, 0);
|
|
|
|
+ if (err < 0) {
|
|
|
|
+ snd_printk(KERN_ERR "%d:%d:%d: return to setting 0 failed (%d)\n",
|
|
|
|
+ dev->devnum, fmt->iface, fmt->altsetting, err);
|
|
|
|
+ return -EIO;
|
|
|
|
+ }
|
|
|
|
+ subs->interface = -1;
|
|
|
|
+ subs->altset_idx = 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* set interface */
|
|
|
|
+ if (subs->interface != fmt->iface ||
|
|
|
|
+ subs->altset_idx != fmt->altset_idx) {
|
|
|
|
+ err = usb_set_interface(dev, fmt->iface, fmt->altsetting);
|
|
|
|
+ if (err < 0) {
|
|
|
|
+ snd_printk(KERN_ERR "%d:%d:%d: usb_set_interface failed (%d)\n",
|
|
|
|
+ dev->devnum, fmt->iface, fmt->altsetting, err);
|
|
|
|
+ return -EIO;
|
|
|
|
+ }
|
|
|
|
+ snd_printdd(KERN_INFO "setting usb interface %d:%d\n",
|
|
|
|
+ fmt->iface, fmt->altsetting);
|
|
|
|
+ subs->interface = fmt->iface;
|
|
|
|
+ subs->altset_idx = fmt->altset_idx;
|
|
|
|
+ }
|
|
|
|
+
|
|
subs->data_endpoint = snd_usb_add_endpoint(subs->stream->chip,
|
|
subs->data_endpoint = snd_usb_add_endpoint(subs->stream->chip,
|
|
alts, fmt->endpoint, subs->direction,
|
|
alts, fmt->endpoint, subs->direction,
|
|
SND_USB_ENDPOINT_TYPE_DATA);
|
|
SND_USB_ENDPOINT_TYPE_DATA);
|
|
@@ -460,12 +474,6 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
|
|
mutex_lock(&subs->stream->chip->shutdown_mutex);
|
|
mutex_lock(&subs->stream->chip->shutdown_mutex);
|
|
/* format changed */
|
|
/* format changed */
|
|
stop_endpoints(subs, 0, 0, 0);
|
|
stop_endpoints(subs, 0, 0, 0);
|
|
- deactivate_endpoints(subs);
|
|
|
|
-
|
|
|
|
- ret = activate_endpoints(subs);
|
|
|
|
- if (ret < 0)
|
|
|
|
- goto unlock;
|
|
|
|
-
|
|
|
|
ret = snd_usb_endpoint_set_params(subs->data_endpoint, hw_params, fmt,
|
|
ret = snd_usb_endpoint_set_params(subs->data_endpoint, hw_params, fmt,
|
|
subs->sync_endpoint);
|
|
subs->sync_endpoint);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
@@ -500,6 +508,7 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
|
|
subs->period_bytes = 0;
|
|
subs->period_bytes = 0;
|
|
mutex_lock(&subs->stream->chip->shutdown_mutex);
|
|
mutex_lock(&subs->stream->chip->shutdown_mutex);
|
|
stop_endpoints(subs, 0, 1, 1);
|
|
stop_endpoints(subs, 0, 1, 1);
|
|
|
|
+ deactivate_endpoints(subs);
|
|
mutex_unlock(&subs->stream->chip->shutdown_mutex);
|
|
mutex_unlock(&subs->stream->chip->shutdown_mutex);
|
|
return snd_pcm_lib_free_vmalloc_buffer(substream);
|
|
return snd_pcm_lib_free_vmalloc_buffer(substream);
|
|
}
|
|
}
|
|
@@ -938,16 +947,20 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
|
|
|
|
|
|
static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
|
|
static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
|
|
{
|
|
{
|
|
- int ret;
|
|
|
|
struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
|
|
struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
|
|
struct snd_usb_substream *subs = &as->substream[direction];
|
|
struct snd_usb_substream *subs = &as->substream[direction];
|
|
|
|
|
|
stop_endpoints(subs, 0, 0, 0);
|
|
stop_endpoints(subs, 0, 0, 0);
|
|
- ret = deactivate_endpoints(subs);
|
|
|
|
|
|
+
|
|
|
|
+ if (!as->chip->shutdown && subs->interface >= 0) {
|
|
|
|
+ usb_set_interface(subs->dev, subs->interface, 0);
|
|
|
|
+ subs->interface = -1;
|
|
|
|
+ }
|
|
|
|
+
|
|
subs->pcm_substream = NULL;
|
|
subs->pcm_substream = NULL;
|
|
snd_usb_autosuspend(subs->stream->chip);
|
|
snd_usb_autosuspend(subs->stream->chip);
|
|
|
|
|
|
- return ret;
|
|
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/* Since a URB can handle only a single linear buffer, we must use double
|
|
/* Since a URB can handle only a single linear buffer, we must use double
|