aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/control.h11
-rw-r--r--sound/core/control.c27
-rw-r--r--sound/core/pcm.c15
-rw-r--r--sound/core/rawmidi.c14
4 files changed, 38 insertions, 29 deletions
diff --git a/include/sound/control.h b/include/sound/control.h
index 042613938a1d..75f3054023f7 100644
--- a/include/sound/control.h
+++ b/include/sound/control.h
@@ -93,12 +93,17 @@ struct snd_kctl_event {
93 93
94struct pid; 94struct pid;
95 95
96enum {
97 SND_CTL_SUBDEV_PCM,
98 SND_CTL_SUBDEV_RAWMIDI,
99 SND_CTL_SUBDEV_ITEMS,
100};
101
96struct snd_ctl_file { 102struct snd_ctl_file {
97 struct list_head list; /* list of all control files */ 103 struct list_head list; /* list of all control files */
98 struct snd_card *card; 104 struct snd_card *card;
99 struct pid *pid; 105 struct pid *pid;
100 int prefer_pcm_subdevice; 106 int preferred_subdevice[SND_CTL_SUBDEV_ITEMS];
101 int prefer_rawmidi_subdevice;
102 wait_queue_head_t change_sleep; 107 wait_queue_head_t change_sleep;
103 spinlock_t read_lock; 108 spinlock_t read_lock;
104 struct fasync_struct *fasync; 109 struct fasync_struct *fasync;
@@ -138,6 +143,8 @@ int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn);
138#define snd_ctl_unregister_ioctl_compat(fcn) 143#define snd_ctl_unregister_ioctl_compat(fcn)
139#endif 144#endif
140 145
146int snd_ctl_get_preferred_subdevice(struct snd_card *card, int type);
147
141static inline unsigned int snd_ctl_get_ioffnum(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id) 148static inline unsigned int snd_ctl_get_ioffnum(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id)
142{ 149{
143 return id->numid - kctl->id.numid; 150 return id->numid - kctl->id.numid;
diff --git a/sound/core/control.c b/sound/core/control.c
index bb96a467e88d..cd246a0bcd55 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -50,7 +50,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
50 unsigned long flags; 50 unsigned long flags;
51 struct snd_card *card; 51 struct snd_card *card;
52 struct snd_ctl_file *ctl; 52 struct snd_ctl_file *ctl;
53 int err; 53 int i, err;
54 54
55 err = nonseekable_open(inode, file); 55 err = nonseekable_open(inode, file);
56 if (err < 0) 56 if (err < 0)
@@ -79,8 +79,8 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
79 init_waitqueue_head(&ctl->change_sleep); 79 init_waitqueue_head(&ctl->change_sleep);
80 spin_lock_init(&ctl->read_lock); 80 spin_lock_init(&ctl->read_lock);
81 ctl->card = card; 81 ctl->card = card;
82 ctl->prefer_pcm_subdevice = -1; 82 for (i = 0; i < SND_CTL_SUBDEV_ITEMS; i++)
83 ctl->prefer_rawmidi_subdevice = -1; 83 ctl->preferred_subdevice[i] = -1;
84 ctl->pid = get_pid(task_pid(current)); 84 ctl->pid = get_pid(task_pid(current));
85 file->private_data = ctl; 85 file->private_data = ctl;
86 write_lock_irqsave(&card->ctl_files_rwlock, flags); 86 write_lock_irqsave(&card->ctl_files_rwlock, flags);
@@ -1607,6 +1607,27 @@ static int snd_ctl_fasync(int fd, struct file * file, int on)
1607 return fasync_helper(fd, file, on, &ctl->fasync); 1607 return fasync_helper(fd, file, on, &ctl->fasync);
1608} 1608}
1609 1609
1610/* return the preferred subdevice number if already assigned;
1611 * otherwise return -1
1612 */
1613int snd_ctl_get_preferred_subdevice(struct snd_card *card, int type)
1614{
1615 struct snd_ctl_file *kctl;
1616 int subdevice = -1;
1617
1618 read_lock(&card->ctl_files_rwlock);
1619 list_for_each_entry(kctl, &card->ctl_files, list) {
1620 if (kctl->pid == task_pid(current)) {
1621 subdevice = kctl->preferred_subdevice[type];
1622 if (subdevice != -1)
1623 break;
1624 }
1625 }
1626 read_unlock(&card->ctl_files_rwlock);
1627 return subdevice;
1628}
1629EXPORT_SYMBOL_GPL(snd_ctl_get_preferred_subdevice);
1630
1610/* 1631/*
1611 * ioctl32 compat 1632 * ioctl32 compat
1612 */ 1633 */
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index dba5180e5b80..1b7c473720fa 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -161,7 +161,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
161 161
162 if (get_user(val, (int __user *)arg)) 162 if (get_user(val, (int __user *)arg))
163 return -EFAULT; 163 return -EFAULT;
164 control->prefer_pcm_subdevice = val; 164 control->preferred_subdevice[SND_CTL_SUBDEV_PCM] = val;
165 return 0; 165 return 0;
166 } 166 }
167 } 167 }
@@ -901,9 +901,8 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
901 struct snd_pcm_str * pstr; 901 struct snd_pcm_str * pstr;
902 struct snd_pcm_substream *substream; 902 struct snd_pcm_substream *substream;
903 struct snd_pcm_runtime *runtime; 903 struct snd_pcm_runtime *runtime;
904 struct snd_ctl_file *kctl;
905 struct snd_card *card; 904 struct snd_card *card;
906 int prefer_subdevice = -1; 905 int prefer_subdevice;
907 size_t size; 906 size_t size;
908 907
909 if (snd_BUG_ON(!pcm || !rsubstream)) 908 if (snd_BUG_ON(!pcm || !rsubstream))
@@ -914,15 +913,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
914 return -ENODEV; 913 return -ENODEV;
915 914
916 card = pcm->card; 915 card = pcm->card;
917 read_lock(&card->ctl_files_rwlock); 916 prefer_subdevice = snd_ctl_get_preferred_subdevice(card, SND_CTL_SUBDEV_PCM);
918 list_for_each_entry(kctl, &card->ctl_files, list) {
919 if (kctl->pid == task_pid(current)) {
920 prefer_subdevice = kctl->prefer_pcm_subdevice;
921 if (prefer_subdevice != -1)
922 break;
923 }
924 }
925 read_unlock(&card->ctl_files_rwlock);
926 917
927 switch (stream) { 918 switch (stream) {
928 case SNDRV_PCM_STREAM_PLAYBACK: 919 case SNDRV_PCM_STREAM_PLAYBACK:
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 6fc71a4c8a51..be18162c380f 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -369,7 +369,6 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
369 struct snd_rawmidi *rmidi; 369 struct snd_rawmidi *rmidi;
370 struct snd_rawmidi_file *rawmidi_file = NULL; 370 struct snd_rawmidi_file *rawmidi_file = NULL;
371 wait_queue_t wait; 371 wait_queue_t wait;
372 struct snd_ctl_file *kctl;
373 372
374 if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK)) 373 if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK))
375 return -EINVAL; /* invalid combination */ 374 return -EINVAL; /* invalid combination */
@@ -413,16 +412,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
413 init_waitqueue_entry(&wait, current); 412 init_waitqueue_entry(&wait, current);
414 add_wait_queue(&rmidi->open_wait, &wait); 413 add_wait_queue(&rmidi->open_wait, &wait);
415 while (1) { 414 while (1) {
416 subdevice = -1; 415 subdevice = snd_ctl_get_preferred_subdevice(card, SND_CTL_SUBDEV_RAWMIDI);
417 read_lock(&card->ctl_files_rwlock);
418 list_for_each_entry(kctl, &card->ctl_files, list) {
419 if (kctl->pid == task_pid(current)) {
420 subdevice = kctl->prefer_rawmidi_subdevice;
421 if (subdevice != -1)
422 break;
423 }
424 }
425 read_unlock(&card->ctl_files_rwlock);
426 err = rawmidi_open_priv(rmidi, subdevice, fflags, rawmidi_file); 416 err = rawmidi_open_priv(rmidi, subdevice, fflags, rawmidi_file);
427 if (err >= 0) 417 if (err >= 0)
428 break; 418 break;
@@ -862,7 +852,7 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card,
862 852
863 if (get_user(val, (int __user *)argp)) 853 if (get_user(val, (int __user *)argp))
864 return -EFAULT; 854 return -EFAULT;
865 control->prefer_rawmidi_subdevice = val; 855 control->preferred_subdevice[SND_CTL_SUBDEV_RAWMIDI] = val;
866 return 0; 856 return 0;
867 } 857 }
868 case SNDRV_CTL_IOCTL_RAWMIDI_INFO: 858 case SNDRV_CTL_IOCTL_RAWMIDI_INFO: