diff options
Diffstat (limited to 'sound/usb/card.c')
| -rw-r--r-- | sound/usb/card.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/sound/usb/card.c b/sound/usb/card.c index 63868d36..b2d3a980 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -110,6 +110,71 @@ static DEFINE_MUTEX(register_mutex); static struct snd_usb_audio *usb_chip[SNDRV_CARDS]; static struct usb_driver usb_audio_driver; +struct snd_usb_substream *find_snd_usb_substream(unsigned int card_num, + unsigned int pcm_idx, unsigned int direction, struct snd_usb_audio + **uchip, void (*disconnect_cb)(struct snd_usb_audio *chip)) +{ + int idx; + struct snd_usb_stream *as; + struct snd_usb_substream *subs = NULL; + struct snd_usb_audio *chip = NULL; + + mutex_lock(®ister_mutex); + /* + * legacy audio snd card number assignment is dynamic. Hence + * search using chip->card->number + */ + for (idx = 0; idx < SNDRV_CARDS; idx++) { + if (!usb_chip[idx]) + continue; + if (usb_chip[idx]->card->number == card_num) { + chip = usb_chip[idx]; + break; + } + } + + if (!chip || chip->shutdown) { + pr_debug("%s: instance of usb crad # %d does not exist\n", + __func__, card_num); + goto err; + } + + if (pcm_idx >= chip->pcm_devs) { + pr_err("%s: invalid pcm dev number %u > %d\n", __func__, + pcm_idx, chip->pcm_devs); + goto err; + } + + if (direction > SNDRV_PCM_STREAM_CAPTURE) { + pr_err("%s: invalid direction %u\n", __func__, direction); + goto err; + } + + list_for_each_entry(as, &chip->pcm_list, list) { + if (as->pcm_index == pcm_idx) { + subs = &as->substream[direction]; + if (subs->interface < 0 && !subs->data_endpoint && + !subs->sync_endpoint) { + pr_debug("%s: stream disconnected, bail out\n", + __func__); + subs = NULL; + goto err; + } + goto done; + } + } + +done: + chip->card_num = card_num; + chip->disconnect_cb = disconnect_cb; +err: + *uchip = chip; + if (!subs) + pr_debug("%s: substream instance not found\n", __func__); + mutex_unlock(®ister_mutex); + return subs; +} + /* * disconnect streams * called from snd_usb_audio_disconnect() @@ -324,6 +389,7 @@ static int snd_usb_audio_free(struct snd_usb_audio *chip) list_for_each_safe(p, n, &chip->ep_list) snd_usb_endpoint_free(p); + mutex_destroy(&chip->dev_lock); mutex_destroy(&chip->mutex); kfree(chip); return 0; @@ -390,6 +456,7 @@ static int snd_usb_audio_create(struct usb_interface *intf, mutex_init(&chip->mutex); init_rwsem(&chip->shutdown_rwsem); + mutex_init(&chip->dev_lock); chip->index = idx; chip->dev = dev; chip->card = card; @@ -614,6 +681,9 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, chip->shutdown = 1; up_write(&chip->shutdown_rwsem); + if (chip->disconnect_cb) + chip->disconnect_cb(chip); + mutex_lock(®ister_mutex); if (!was_shutdown) { struct snd_usb_endpoint *ep; |
