Commit 23c18d4b authored by Takashi Iwai's avatar Takashi Iwai

ALSA: control: Provide a helper to look for the preferred subdevice

Instead of open-coding the search over the control file loop, provide
a helper function for the preferred subdevice assigned to the current
process.
Reviewed-by: default avatarJaroslav Kysela <perex@perex.cz>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 92b7952d
...@@ -93,12 +93,17 @@ struct snd_kctl_event { ...@@ -93,12 +93,17 @@ struct snd_kctl_event {
struct pid; struct pid;
enum {
SND_CTL_SUBDEV_PCM,
SND_CTL_SUBDEV_RAWMIDI,
SND_CTL_SUBDEV_ITEMS,
};
struct snd_ctl_file { struct snd_ctl_file {
struct list_head list; /* list of all control files */ struct list_head list; /* list of all control files */
struct snd_card *card; struct snd_card *card;
struct pid *pid; struct pid *pid;
int prefer_pcm_subdevice; int preferred_subdevice[SND_CTL_SUBDEV_ITEMS];
int prefer_rawmidi_subdevice;
wait_queue_head_t change_sleep; wait_queue_head_t change_sleep;
spinlock_t read_lock; spinlock_t read_lock;
struct fasync_struct *fasync; struct fasync_struct *fasync;
...@@ -138,6 +143,8 @@ int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn); ...@@ -138,6 +143,8 @@ int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn);
#define snd_ctl_unregister_ioctl_compat(fcn) #define snd_ctl_unregister_ioctl_compat(fcn)
#endif #endif
int snd_ctl_get_preferred_subdevice(struct snd_card *card, int type);
static inline unsigned int snd_ctl_get_ioffnum(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id) static inline unsigned int snd_ctl_get_ioffnum(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id)
{ {
return id->numid - kctl->id.numid; return id->numid - kctl->id.numid;
......
...@@ -50,7 +50,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file) ...@@ -50,7 +50,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
unsigned long flags; unsigned long flags;
struct snd_card *card; struct snd_card *card;
struct snd_ctl_file *ctl; struct snd_ctl_file *ctl;
int err; int i, err;
err = nonseekable_open(inode, file); err = nonseekable_open(inode, file);
if (err < 0) if (err < 0)
...@@ -79,8 +79,8 @@ static int snd_ctl_open(struct inode *inode, struct file *file) ...@@ -79,8 +79,8 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
init_waitqueue_head(&ctl->change_sleep); init_waitqueue_head(&ctl->change_sleep);
spin_lock_init(&ctl->read_lock); spin_lock_init(&ctl->read_lock);
ctl->card = card; ctl->card = card;
ctl->prefer_pcm_subdevice = -1; for (i = 0; i < SND_CTL_SUBDEV_ITEMS; i++)
ctl->prefer_rawmidi_subdevice = -1; ctl->preferred_subdevice[i] = -1;
ctl->pid = get_pid(task_pid(current)); ctl->pid = get_pid(task_pid(current));
file->private_data = ctl; file->private_data = ctl;
write_lock_irqsave(&card->ctl_files_rwlock, flags); 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,6 +1607,27 @@ static int snd_ctl_fasync(int fd, struct file * file, int on)
return fasync_helper(fd, file, on, &ctl->fasync); return fasync_helper(fd, file, on, &ctl->fasync);
} }
/* return the preferred subdevice number if already assigned;
* otherwise return -1
*/
int snd_ctl_get_preferred_subdevice(struct snd_card *card, int type)
{
struct snd_ctl_file *kctl;
int subdevice = -1;
read_lock(&card->ctl_files_rwlock);
list_for_each_entry(kctl, &card->ctl_files, list) {
if (kctl->pid == task_pid(current)) {
subdevice = kctl->preferred_subdevice[type];
if (subdevice != -1)
break;
}
}
read_unlock(&card->ctl_files_rwlock);
return subdevice;
}
EXPORT_SYMBOL_GPL(snd_ctl_get_preferred_subdevice);
/* /*
* ioctl32 compat * ioctl32 compat
*/ */
......
...@@ -161,7 +161,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card, ...@@ -161,7 +161,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
if (get_user(val, (int __user *)arg)) if (get_user(val, (int __user *)arg))
return -EFAULT; return -EFAULT;
control->prefer_pcm_subdevice = val; control->preferred_subdevice[SND_CTL_SUBDEV_PCM] = val;
return 0; return 0;
} }
} }
...@@ -901,9 +901,8 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, ...@@ -901,9 +901,8 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
struct snd_pcm_str * pstr; struct snd_pcm_str * pstr;
struct snd_pcm_substream *substream; struct snd_pcm_substream *substream;
struct snd_pcm_runtime *runtime; struct snd_pcm_runtime *runtime;
struct snd_ctl_file *kctl;
struct snd_card *card; struct snd_card *card;
int prefer_subdevice = -1; int prefer_subdevice;
size_t size; size_t size;
if (snd_BUG_ON(!pcm || !rsubstream)) if (snd_BUG_ON(!pcm || !rsubstream))
...@@ -914,15 +913,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, ...@@ -914,15 +913,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
return -ENODEV; return -ENODEV;
card = pcm->card; card = pcm->card;
read_lock(&card->ctl_files_rwlock); prefer_subdevice = snd_ctl_get_preferred_subdevice(card, SND_CTL_SUBDEV_PCM);
list_for_each_entry(kctl, &card->ctl_files, list) {
if (kctl->pid == task_pid(current)) {
prefer_subdevice = kctl->prefer_pcm_subdevice;
if (prefer_subdevice != -1)
break;
}
}
read_unlock(&card->ctl_files_rwlock);
switch (stream) { switch (stream) {
case SNDRV_PCM_STREAM_PLAYBACK: case SNDRV_PCM_STREAM_PLAYBACK:
......
...@@ -369,7 +369,6 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) ...@@ -369,7 +369,6 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
struct snd_rawmidi *rmidi; struct snd_rawmidi *rmidi;
struct snd_rawmidi_file *rawmidi_file = NULL; struct snd_rawmidi_file *rawmidi_file = NULL;
wait_queue_t wait; wait_queue_t wait;
struct snd_ctl_file *kctl;
if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK)) if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK))
return -EINVAL; /* invalid combination */ return -EINVAL; /* invalid combination */
...@@ -413,16 +412,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) ...@@ -413,16 +412,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
init_waitqueue_entry(&wait, current); init_waitqueue_entry(&wait, current);
add_wait_queue(&rmidi->open_wait, &wait); add_wait_queue(&rmidi->open_wait, &wait);
while (1) { while (1) {
subdevice = -1; subdevice = snd_ctl_get_preferred_subdevice(card, SND_CTL_SUBDEV_RAWMIDI);
read_lock(&card->ctl_files_rwlock);
list_for_each_entry(kctl, &card->ctl_files, list) {
if (kctl->pid == task_pid(current)) {
subdevice = kctl->prefer_rawmidi_subdevice;
if (subdevice != -1)
break;
}
}
read_unlock(&card->ctl_files_rwlock);
err = rawmidi_open_priv(rmidi, subdevice, fflags, rawmidi_file); err = rawmidi_open_priv(rmidi, subdevice, fflags, rawmidi_file);
if (err >= 0) if (err >= 0)
break; break;
...@@ -862,7 +852,7 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card, ...@@ -862,7 +852,7 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card,
if (get_user(val, (int __user *)argp)) if (get_user(val, (int __user *)argp))
return -EFAULT; return -EFAULT;
control->prefer_rawmidi_subdevice = val; control->preferred_subdevice[SND_CTL_SUBDEV_RAWMIDI] = val;
return 0; return 0;
} }
case SNDRV_CTL_IOCTL_RAWMIDI_INFO: case SNDRV_CTL_IOCTL_RAWMIDI_INFO:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment