diff options
Diffstat (limited to 'sound/core/pcm.c')
-rw-r--r-- | sound/core/pcm.c | 84 |
1 files changed, 56 insertions, 28 deletions
diff --git a/sound/core/pcm.c b/sound/core/pcm.c index ece25c718e95..192a433a2403 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c | |||
@@ -42,7 +42,7 @@ static int snd_pcm_dev_free(struct snd_device *device); | |||
42 | static int snd_pcm_dev_register(struct snd_device *device); | 42 | static int snd_pcm_dev_register(struct snd_device *device); |
43 | static int snd_pcm_dev_disconnect(struct snd_device *device); | 43 | static int snd_pcm_dev_disconnect(struct snd_device *device); |
44 | 44 | ||
45 | static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device) | 45 | static struct snd_pcm *snd_pcm_get(struct snd_card *card, int device) |
46 | { | 46 | { |
47 | struct snd_pcm *pcm; | 47 | struct snd_pcm *pcm; |
48 | 48 | ||
@@ -53,6 +53,37 @@ static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device) | |||
53 | return NULL; | 53 | return NULL; |
54 | } | 54 | } |
55 | 55 | ||
56 | static int snd_pcm_next(struct snd_card *card, int device) | ||
57 | { | ||
58 | struct snd_pcm *pcm; | ||
59 | |||
60 | list_for_each_entry(pcm, &snd_pcm_devices, list) { | ||
61 | if (pcm->card == card && pcm->device > device) | ||
62 | return pcm->device; | ||
63 | else if (pcm->card->number > card->number) | ||
64 | return -1; | ||
65 | } | ||
66 | return -1; | ||
67 | } | ||
68 | |||
69 | static int snd_pcm_add(struct snd_pcm *newpcm) | ||
70 | { | ||
71 | struct snd_pcm *pcm; | ||
72 | |||
73 | list_for_each_entry(pcm, &snd_pcm_devices, list) { | ||
74 | if (pcm->card == newpcm->card && pcm->device == newpcm->device) | ||
75 | return -EBUSY; | ||
76 | if (pcm->card->number > newpcm->card->number || | ||
77 | (pcm->card == newpcm->card && | ||
78 | pcm->device > newpcm->device)) { | ||
79 | list_add(&newpcm->list, pcm->list.prev); | ||
80 | return 0; | ||
81 | } | ||
82 | } | ||
83 | list_add_tail(&newpcm->list, &snd_pcm_devices); | ||
84 | return 0; | ||
85 | } | ||
86 | |||
56 | static int snd_pcm_control_ioctl(struct snd_card *card, | 87 | static int snd_pcm_control_ioctl(struct snd_card *card, |
57 | struct snd_ctl_file *control, | 88 | struct snd_ctl_file *control, |
58 | unsigned int cmd, unsigned long arg) | 89 | unsigned int cmd, unsigned long arg) |
@@ -65,14 +96,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card, | |||
65 | if (get_user(device, (int __user *)arg)) | 96 | if (get_user(device, (int __user *)arg)) |
66 | return -EFAULT; | 97 | return -EFAULT; |
67 | mutex_lock(®ister_mutex); | 98 | mutex_lock(®ister_mutex); |
68 | device = device < 0 ? 0 : device + 1; | 99 | device = snd_pcm_next(card, device); |
69 | while (device < SNDRV_PCM_DEVICES) { | ||
70 | if (snd_pcm_search(card, device)) | ||
71 | break; | ||
72 | device++; | ||
73 | } | ||
74 | if (device == SNDRV_PCM_DEVICES) | ||
75 | device = -1; | ||
76 | mutex_unlock(®ister_mutex); | 100 | mutex_unlock(®ister_mutex); |
77 | if (put_user(device, (int __user *)arg)) | 101 | if (put_user(device, (int __user *)arg)) |
78 | return -EFAULT; | 102 | return -EFAULT; |
@@ -98,7 +122,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card, | |||
98 | if (get_user(subdevice, &info->subdevice)) | 122 | if (get_user(subdevice, &info->subdevice)) |
99 | return -EFAULT; | 123 | return -EFAULT; |
100 | mutex_lock(®ister_mutex); | 124 | mutex_lock(®ister_mutex); |
101 | pcm = snd_pcm_search(card, device); | 125 | pcm = snd_pcm_get(card, device); |
102 | if (pcm == NULL) { | 126 | if (pcm == NULL) { |
103 | err = -ENXIO; | 127 | err = -ENXIO; |
104 | goto _error; | 128 | goto _error; |
@@ -232,7 +256,6 @@ static char *snd_pcm_tstamp_mode_names[] = { | |||
232 | 256 | ||
233 | static const char *snd_pcm_stream_name(int stream) | 257 | static const char *snd_pcm_stream_name(int stream) |
234 | { | 258 | { |
235 | snd_assert(stream <= SNDRV_PCM_STREAM_LAST, return NULL); | ||
236 | return snd_pcm_stream_names[stream]; | 259 | return snd_pcm_stream_names[stream]; |
237 | } | 260 | } |
238 | 261 | ||
@@ -248,7 +271,6 @@ static const char *snd_pcm_subformat_name(snd_pcm_subformat_t subformat) | |||
248 | 271 | ||
249 | static const char *snd_pcm_tstamp_mode_name(int mode) | 272 | static const char *snd_pcm_tstamp_mode_name(int mode) |
250 | { | 273 | { |
251 | snd_assert(mode <= SNDRV_PCM_TSTAMP_LAST, return NULL); | ||
252 | return snd_pcm_tstamp_mode_names[mode]; | 274 | return snd_pcm_tstamp_mode_names[mode]; |
253 | } | 275 | } |
254 | 276 | ||
@@ -682,9 +704,10 @@ int snd_pcm_new(struct snd_card *card, char *id, int device, | |||
682 | .dev_disconnect = snd_pcm_dev_disconnect, | 704 | .dev_disconnect = snd_pcm_dev_disconnect, |
683 | }; | 705 | }; |
684 | 706 | ||
685 | snd_assert(rpcm != NULL, return -EINVAL); | 707 | if (snd_BUG_ON(!card)) |
686 | *rpcm = NULL; | 708 | return -ENXIO; |
687 | snd_assert(card != NULL, return -ENXIO); | 709 | if (rpcm) |
710 | *rpcm = NULL; | ||
688 | pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); | 711 | pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); |
689 | if (pcm == NULL) { | 712 | if (pcm == NULL) { |
690 | snd_printk(KERN_ERR "Cannot allocate PCM\n"); | 713 | snd_printk(KERN_ERR "Cannot allocate PCM\n"); |
@@ -708,7 +731,8 @@ int snd_pcm_new(struct snd_card *card, char *id, int device, | |||
708 | snd_pcm_free(pcm); | 731 | snd_pcm_free(pcm); |
709 | return err; | 732 | return err; |
710 | } | 733 | } |
711 | *rpcm = pcm; | 734 | if (rpcm) |
735 | *rpcm = pcm; | ||
712 | return 0; | 736 | return 0; |
713 | } | 737 | } |
714 | 738 | ||
@@ -742,7 +766,8 @@ static int snd_pcm_free(struct snd_pcm *pcm) | |||
742 | { | 766 | { |
743 | struct snd_pcm_notify *notify; | 767 | struct snd_pcm_notify *notify; |
744 | 768 | ||
745 | snd_assert(pcm != NULL, return -ENXIO); | 769 | if (!pcm) |
770 | return 0; | ||
746 | list_for_each_entry(notify, &snd_pcm_notify_list, list) { | 771 | list_for_each_entry(notify, &snd_pcm_notify_list, list) { |
747 | notify->n_unregister(pcm); | 772 | notify->n_unregister(pcm); |
748 | } | 773 | } |
@@ -773,9 +798,9 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, | |||
773 | int prefer_subdevice = -1; | 798 | int prefer_subdevice = -1; |
774 | size_t size; | 799 | size_t size; |
775 | 800 | ||
776 | snd_assert(rsubstream != NULL, return -EINVAL); | 801 | if (snd_BUG_ON(!pcm || !rsubstream)) |
802 | return -ENXIO; | ||
777 | *rsubstream = NULL; | 803 | *rsubstream = NULL; |
778 | snd_assert(pcm != NULL, return -ENXIO); | ||
779 | pstr = &pcm->streams[stream]; | 804 | pstr = &pcm->streams[stream]; |
780 | if (pstr->substream == NULL || pstr->substream_count == 0) | 805 | if (pstr->substream == NULL || pstr->substream_count == 0) |
781 | return -ENODEV; | 806 | return -ENODEV; |
@@ -883,8 +908,9 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream) | |||
883 | { | 908 | { |
884 | struct snd_pcm_runtime *runtime; | 909 | struct snd_pcm_runtime *runtime; |
885 | 910 | ||
911 | if (PCM_RUNTIME_CHECK(substream)) | ||
912 | return; | ||
886 | runtime = substream->runtime; | 913 | runtime = substream->runtime; |
887 | snd_assert(runtime != NULL, return); | ||
888 | if (runtime->private_free != NULL) | 914 | if (runtime->private_free != NULL) |
889 | runtime->private_free(runtime); | 915 | runtime->private_free(runtime); |
890 | snd_free_pages((void*)runtime->status, | 916 | snd_free_pages((void*)runtime->status, |
@@ -929,13 +955,14 @@ static int snd_pcm_dev_register(struct snd_device *device) | |||
929 | struct snd_pcm *pcm = device->device_data; | 955 | struct snd_pcm *pcm = device->device_data; |
930 | struct device *dev; | 956 | struct device *dev; |
931 | 957 | ||
932 | snd_assert(pcm != NULL && device != NULL, return -ENXIO); | 958 | if (snd_BUG_ON(!pcm || !device)) |
959 | return -ENXIO; | ||
933 | mutex_lock(®ister_mutex); | 960 | mutex_lock(®ister_mutex); |
934 | if (snd_pcm_search(pcm->card, pcm->device)) { | 961 | err = snd_pcm_add(pcm); |
962 | if (err) { | ||
935 | mutex_unlock(®ister_mutex); | 963 | mutex_unlock(®ister_mutex); |
936 | return -EBUSY; | 964 | return err; |
937 | } | 965 | } |
938 | list_add_tail(&pcm->list, &snd_pcm_devices); | ||
939 | for (cidx = 0; cidx < 2; cidx++) { | 966 | for (cidx = 0; cidx < 2; cidx++) { |
940 | int devtype = -1; | 967 | int devtype = -1; |
941 | if (pcm->streams[cidx].substream == NULL) | 968 | if (pcm->streams[cidx].substream == NULL) |
@@ -1019,10 +1046,11 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree) | |||
1019 | { | 1046 | { |
1020 | struct snd_pcm *pcm; | 1047 | struct snd_pcm *pcm; |
1021 | 1048 | ||
1022 | snd_assert(notify != NULL && | 1049 | if (snd_BUG_ON(!notify || |
1023 | notify->n_register != NULL && | 1050 | !notify->n_register || |
1024 | notify->n_unregister != NULL && | 1051 | !notify->n_unregister || |
1025 | notify->n_disconnect, return -EINVAL); | 1052 | !notify->n_disconnect)) |
1053 | return -EINVAL; | ||
1026 | mutex_lock(®ister_mutex); | 1054 | mutex_lock(®ister_mutex); |
1027 | if (nfree) { | 1055 | if (nfree) { |
1028 | list_del(¬ify->list); | 1056 | list_del(¬ify->list); |