Commit f87135f5 authored by Clemens Ladisch's avatar Clemens Ladisch Committed by Jaroslav Kysela

[ALSA] dynamic minors (3/6): store device-specific object pointers dynamically

Instead of storing the pointers to the device-specific structures in an
array, put them into the struct snd_minor, and look them up dynamically.

This makes the device type modules independent of the minor number
encoding.
Signed-off-by: default avatarClemens Ladisch <clemens@ladisch.de>
parent 6983b724
...@@ -187,6 +187,7 @@ struct snd_minor { ...@@ -187,6 +187,7 @@ struct snd_minor {
int card; /* card number */ int card; /* card number */
int device; /* device number */ int device; /* device number */
struct file_operations *f_ops; /* file operations */ struct file_operations *f_ops; /* file operations */
void *private_data; /* private data for f_ops->open */
char name[0]; /* device name (keep at the end of char name[0]; /* device name (keep at the end of
structure) */ structure) */
}; };
...@@ -199,13 +200,17 @@ extern int snd_ecards_limit; ...@@ -199,13 +200,17 @@ extern int snd_ecards_limit;
void snd_request_card(int card); void snd_request_card(int card);
int snd_register_device(int type, struct snd_card *card, int dev, int snd_register_device(int type, struct snd_card *card, int dev,
struct file_operations *f_ops, const char *name); struct file_operations *f_ops, void *private_data,
const char *name);
int snd_unregister_device(int type, struct snd_card *card, int dev); int snd_unregister_device(int type, struct snd_card *card, int dev);
void *snd_lookup_minor_data(unsigned int minor, int type);
#ifdef CONFIG_SND_OSSEMUL #ifdef CONFIG_SND_OSSEMUL
int snd_register_oss_device(int type, struct snd_card *card, int dev, int snd_register_oss_device(int type, struct snd_card *card, int dev,
struct file_operations *f_ops, const char *name); struct file_operations *f_ops, void *private_data,
const char *name);
int snd_unregister_oss_device(int type, struct snd_card *card, int dev); int snd_unregister_oss_device(int type, struct snd_card *card, int dev);
void *snd_lookup_oss_minor_data(unsigned int minor, int type);
#endif #endif
int snd_minor_info_init(void); int snd_minor_info_init(void);
......
...@@ -43,6 +43,7 @@ struct snd_hwdep_ops { ...@@ -43,6 +43,7 @@ struct snd_hwdep_ops {
struct snd_hwdep { struct snd_hwdep {
struct snd_card *card; struct snd_card *card;
struct list_head list;
int device; int device;
char id[32]; char id[32];
char name[80]; char name[80];
......
...@@ -412,6 +412,7 @@ struct snd_pcm_str { ...@@ -412,6 +412,7 @@ struct snd_pcm_str {
struct snd_pcm { struct snd_pcm {
struct snd_card *card; struct snd_card *card;
struct list_head list;
unsigned int device; /* device number */ unsigned int device; /* device number */
unsigned int info_flags; unsigned int info_flags;
unsigned short dev_class; unsigned short dev_class;
...@@ -439,7 +440,6 @@ struct snd_pcm_notify { ...@@ -439,7 +440,6 @@ struct snd_pcm_notify {
* Registering * Registering
*/ */
extern struct snd_pcm *snd_pcm_devices[];
extern struct file_operations snd_pcm_f_ops[2]; extern struct file_operations snd_pcm_f_ops[2];
int snd_pcm_new(struct snd_card *card, char *id, int device, int snd_pcm_new(struct snd_card *card, char *id, int device,
......
...@@ -113,7 +113,7 @@ struct snd_rawmidi_str { ...@@ -113,7 +113,7 @@ struct snd_rawmidi_str {
struct snd_rawmidi { struct snd_rawmidi {
struct snd_card *card; struct snd_card *card;
struct list_head list;
unsigned int device; /* device number */ unsigned int device; /* device number */
unsigned int info_flags; /* SNDRV_RAWMIDI_INFO_XXXX */ unsigned int info_flags; /* SNDRV_RAWMIDI_INFO_XXXX */
char id[64]; char id[64];
...@@ -165,8 +165,8 @@ int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream, ...@@ -165,8 +165,8 @@ int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,
/* main midi functions */ /* main midi functions */
int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info); int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info);
int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice, int mode, int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice,
struct snd_rawmidi_file *rfile); int mode, struct snd_rawmidi_file *rfile);
int snd_rawmidi_kernel_release(struct snd_rawmidi_file *rfile); int snd_rawmidi_kernel_release(struct snd_rawmidi_file *rfile);
int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream, int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream,
struct snd_rawmidi_params *params); struct snd_rawmidi_params *params);
......
...@@ -47,13 +47,12 @@ static LIST_HEAD(snd_control_compat_ioctls); ...@@ -47,13 +47,12 @@ static LIST_HEAD(snd_control_compat_ioctls);
static int snd_ctl_open(struct inode *inode, struct file *file) static int snd_ctl_open(struct inode *inode, struct file *file)
{ {
int cardnum = SNDRV_MINOR_CARD(iminor(inode));
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 err;
card = snd_cards[cardnum]; card = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_CONTROL);
if (!card) { if (!card) {
err = -ENODEV; err = -ENODEV;
goto __error1; goto __error1;
...@@ -1277,8 +1276,8 @@ static int snd_ctl_dev_register(struct snd_device *device) ...@@ -1277,8 +1276,8 @@ static int snd_ctl_dev_register(struct snd_device *device)
cardnum = card->number; cardnum = card->number;
snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO); snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO);
sprintf(name, "controlC%i", cardnum); sprintf(name, "controlC%i", cardnum);
if ((err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, if ((err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1,
card, -1, &snd_ctl_f_ops, name)) < 0) &snd_ctl_f_ops, card, name)) < 0)
return err; return err;
return 0; return 0;
} }
......
...@@ -35,8 +35,7 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); ...@@ -35,8 +35,7 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
MODULE_DESCRIPTION("Hardware dependent layer"); MODULE_DESCRIPTION("Hardware dependent layer");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static struct snd_hwdep *snd_hwdep_devices[SNDRV_CARDS * SNDRV_MINOR_HWDEPS]; static LIST_HEAD(snd_hwdep_devices);
static DECLARE_MUTEX(register_mutex); static DECLARE_MUTEX(register_mutex);
static int snd_hwdep_free(struct snd_hwdep *hwdep); static int snd_hwdep_free(struct snd_hwdep *hwdep);
...@@ -44,9 +43,19 @@ static int snd_hwdep_dev_free(struct snd_device *device); ...@@ -44,9 +43,19 @@ static int snd_hwdep_dev_free(struct snd_device *device);
static int snd_hwdep_dev_register(struct snd_device *device); static int snd_hwdep_dev_register(struct snd_device *device);
static int snd_hwdep_dev_unregister(struct snd_device *device); static int snd_hwdep_dev_unregister(struct snd_device *device);
/*
*/ static struct snd_hwdep *snd_hwdep_search(struct snd_card *card, int device)
{
struct list_head *p;
struct snd_hwdep *hwdep;
list_for_each(p, &snd_hwdep_devices) {
hwdep = list_entry(p, struct snd_hwdep, list);
if (hwdep->card == card && hwdep->device == device)
return hwdep;
}
return NULL;
}
static loff_t snd_hwdep_llseek(struct file * file, loff_t offset, int orig) static loff_t snd_hwdep_llseek(struct file * file, loff_t offset, int orig)
{ {
...@@ -77,34 +86,25 @@ static ssize_t snd_hwdep_write(struct file * file, const char __user *buf, ...@@ -77,34 +86,25 @@ static ssize_t snd_hwdep_write(struct file * file, const char __user *buf,
static int snd_hwdep_open(struct inode *inode, struct file * file) static int snd_hwdep_open(struct inode *inode, struct file * file)
{ {
int major = imajor(inode); int major = imajor(inode);
int cardnum;
int device;
struct snd_hwdep *hw; struct snd_hwdep *hw;
int err; int err;
wait_queue_t wait; wait_queue_t wait;
if (major == snd_major) { if (major == snd_major) {
cardnum = SNDRV_MINOR_CARD(iminor(inode)); hw = snd_lookup_minor_data(iminor(inode),
device = SNDRV_MINOR_DEVICE(iminor(inode)) - SNDRV_MINOR_HWDEP; SNDRV_DEVICE_TYPE_HWDEP);
#ifdef CONFIG_SND_OSSEMUL #ifdef CONFIG_SND_OSSEMUL
} else if (major == SOUND_MAJOR) { } else if (major == SOUND_MAJOR) {
cardnum = SNDRV_MINOR_OSS_CARD(iminor(inode)); hw = snd_lookup_oss_minor_data(iminor(inode),
device = 0; SNDRV_OSS_DEVICE_TYPE_DMFM);
#endif #endif
} else } else
return -ENXIO; return -ENXIO;
cardnum %= SNDRV_CARDS;
device %= SNDRV_MINOR_HWDEPS;
hw = snd_hwdep_devices[(cardnum * SNDRV_MINOR_HWDEPS) + device];
if (hw == NULL) if (hw == NULL)
return -ENODEV; return -ENODEV;
if (!hw->ops.open) if (!hw->ops.open)
return -ENXIO; return -ENXIO;
#ifdef CONFIG_SND_OSSEMUL
if (major == SOUND_MAJOR && hw->oss_type < 0)
return -ENXIO;
#endif
if (!try_module_get(hw->card->module)) if (!try_module_get(hw->card->module))
return -EFAULT; return -EFAULT;
...@@ -265,9 +265,6 @@ static int snd_hwdep_control_ioctl(struct snd_card *card, ...@@ -265,9 +265,6 @@ static int snd_hwdep_control_ioctl(struct snd_card *card,
struct snd_ctl_file * control, struct snd_ctl_file * control,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
unsigned int tmp;
tmp = card->number * SNDRV_MINOR_HWDEPS;
switch (cmd) { switch (cmd) {
case SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE: case SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE:
{ {
...@@ -275,14 +272,16 @@ static int snd_hwdep_control_ioctl(struct snd_card *card, ...@@ -275,14 +272,16 @@ static int snd_hwdep_control_ioctl(struct snd_card *card,
if (get_user(device, (int __user *)arg)) if (get_user(device, (int __user *)arg))
return -EFAULT; return -EFAULT;
down(&register_mutex);
device = device < 0 ? 0 : device + 1; device = device < 0 ? 0 : device + 1;
while (device < SNDRV_MINOR_HWDEPS) { while (device < SNDRV_MINOR_HWDEPS) {
if (snd_hwdep_devices[tmp + device]) if (snd_hwdep_search(card, device))
break; break;
device++; device++;
} }
if (device >= SNDRV_MINOR_HWDEPS) if (device >= SNDRV_MINOR_HWDEPS)
device = -1; device = -1;
up(&register_mutex);
if (put_user(device, (int __user *)arg)) if (put_user(device, (int __user *)arg))
return -EFAULT; return -EFAULT;
return 0; return 0;
...@@ -290,17 +289,19 @@ static int snd_hwdep_control_ioctl(struct snd_card *card, ...@@ -290,17 +289,19 @@ static int snd_hwdep_control_ioctl(struct snd_card *card,
case SNDRV_CTL_IOCTL_HWDEP_INFO: case SNDRV_CTL_IOCTL_HWDEP_INFO:
{ {
struct snd_hwdep_info __user *info = (struct snd_hwdep_info __user *)arg; struct snd_hwdep_info __user *info = (struct snd_hwdep_info __user *)arg;
int device; int device, err;
struct snd_hwdep *hwdep; struct snd_hwdep *hwdep;
if (get_user(device, &info->device)) if (get_user(device, &info->device))
return -EFAULT; return -EFAULT;
if (device < 0 || device >= SNDRV_MINOR_HWDEPS) down(&register_mutex);
return -ENXIO; hwdep = snd_hwdep_search(card, device);
hwdep = snd_hwdep_devices[tmp + device]; if (hwdep)
if (hwdep == NULL) err = snd_hwdep_info(hwdep, info);
return -ENXIO; else
return snd_hwdep_info(hwdep, info); err = -ENXIO;
up(&register_mutex);
return err;
} }
} }
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
...@@ -397,23 +398,22 @@ static int snd_hwdep_dev_free(struct snd_device *device) ...@@ -397,23 +398,22 @@ static int snd_hwdep_dev_free(struct snd_device *device)
static int snd_hwdep_dev_register(struct snd_device *device) static int snd_hwdep_dev_register(struct snd_device *device)
{ {
struct snd_hwdep *hwdep = device->device_data; struct snd_hwdep *hwdep = device->device_data;
int idx, err; int err;
char name[32]; char name[32];
down(&register_mutex); down(&register_mutex);
idx = (hwdep->card->number * SNDRV_MINOR_HWDEPS) + hwdep->device; if (snd_hwdep_search(hwdep->card, hwdep->device)) {
if (snd_hwdep_devices[idx]) {
up(&register_mutex); up(&register_mutex);
return -EBUSY; return -EBUSY;
} }
snd_hwdep_devices[idx] = hwdep; list_add_tail(&hwdep->list, &snd_hwdep_devices);
sprintf(name, "hwC%iD%i", hwdep->card->number, hwdep->device); sprintf(name, "hwC%iD%i", hwdep->card->number, hwdep->device);
if ((err = snd_register_device(SNDRV_DEVICE_TYPE_HWDEP, if ((err = snd_register_device(SNDRV_DEVICE_TYPE_HWDEP,
hwdep->card, hwdep->device, hwdep->card, hwdep->device,
&snd_hwdep_f_ops, name)) < 0) { &snd_hwdep_f_ops, hwdep, name)) < 0) {
snd_printk(KERN_ERR "unable to register hardware dependent device %i:%i\n", snd_printk(KERN_ERR "unable to register hardware dependent device %i:%i\n",
hwdep->card->number, hwdep->device); hwdep->card->number, hwdep->device);
snd_hwdep_devices[idx] = NULL; list_del(&hwdep->list);
up(&register_mutex); up(&register_mutex);
return err; return err;
} }
...@@ -425,7 +425,7 @@ static int snd_hwdep_dev_register(struct snd_device *device) ...@@ -425,7 +425,7 @@ static int snd_hwdep_dev_register(struct snd_device *device)
} else { } else {
if (snd_register_oss_device(hwdep->oss_type, if (snd_register_oss_device(hwdep->oss_type,
hwdep->card, hwdep->device, hwdep->card, hwdep->device,
&snd_hwdep_f_ops, &snd_hwdep_f_ops, hwdep,
hwdep->oss_dev) < 0) { hwdep->oss_dev) < 0) {
snd_printk(KERN_ERR "unable to register OSS compatibility device %i:%i\n", snd_printk(KERN_ERR "unable to register OSS compatibility device %i:%i\n",
hwdep->card->number, hwdep->device); hwdep->card->number, hwdep->device);
...@@ -441,12 +441,10 @@ static int snd_hwdep_dev_register(struct snd_device *device) ...@@ -441,12 +441,10 @@ static int snd_hwdep_dev_register(struct snd_device *device)
static int snd_hwdep_dev_unregister(struct snd_device *device) static int snd_hwdep_dev_unregister(struct snd_device *device)
{ {
struct snd_hwdep *hwdep = device->device_data; struct snd_hwdep *hwdep = device->device_data;
int idx;
snd_assert(hwdep != NULL, return -ENXIO); snd_assert(hwdep != NULL, return -ENXIO);
down(&register_mutex); down(&register_mutex);
idx = (hwdep->card->number * SNDRV_MINOR_HWDEPS) + hwdep->device; if (snd_hwdep_search(hwdep->card, hwdep->device) != hwdep) {
if (snd_hwdep_devices[idx] != hwdep) {
up(&register_mutex); up(&register_mutex);
return -EINVAL; return -EINVAL;
} }
...@@ -455,7 +453,7 @@ static int snd_hwdep_dev_unregister(struct snd_device *device) ...@@ -455,7 +453,7 @@ static int snd_hwdep_dev_unregister(struct snd_device *device)
snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device); snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device);
#endif #endif
snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device); snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device);
snd_hwdep_devices[idx] = NULL; list_del(&hwdep->list);
up(&register_mutex); up(&register_mutex);
return snd_hwdep_free(hwdep); return snd_hwdep_free(hwdep);
} }
...@@ -467,18 +465,14 @@ static int snd_hwdep_dev_unregister(struct snd_device *device) ...@@ -467,18 +465,14 @@ static int snd_hwdep_dev_unregister(struct snd_device *device)
static void snd_hwdep_proc_read(struct snd_info_entry *entry, static void snd_hwdep_proc_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer) struct snd_info_buffer *buffer)
{ {
int idx; struct list_head *p;
struct snd_hwdep *hwdep; struct snd_hwdep *hwdep;
down(&register_mutex); down(&register_mutex);
for (idx = 0; idx < SNDRV_CARDS * SNDRV_MINOR_HWDEPS; idx++) { list_for_each(p, &snd_hwdep_devices) {
hwdep = snd_hwdep_devices[idx]; hwdep = list_entry(p, struct snd_hwdep, list);
if (hwdep == NULL)
continue;
snd_iprintf(buffer, "%02i-%02i: %s\n", snd_iprintf(buffer, "%02i-%02i: %s\n",
idx / SNDRV_MINOR_HWDEPS, hwdep->card->number, hwdep->device, hwdep->name);
idx % SNDRV_MINOR_HWDEPS,
hwdep->name);
} }
up(&register_mutex); up(&register_mutex);
} }
...@@ -493,9 +487,8 @@ static int __init alsa_hwdep_init(void) ...@@ -493,9 +487,8 @@ static int __init alsa_hwdep_init(void)
{ {
struct snd_info_entry *entry; struct snd_info_entry *entry;
memset(snd_hwdep_devices, 0, sizeof(snd_hwdep_devices));
if ((entry = snd_info_create_module_entry(THIS_MODULE, "hwdep", NULL)) != NULL) { if ((entry = snd_info_create_module_entry(THIS_MODULE, "hwdep", NULL)) != NULL) {
entry->c.text.read_size = 512; entry->c.text.read_size = PAGE_SIZE;
entry->c.text.read = snd_hwdep_proc_read; entry->c.text.read = snd_hwdep_proc_read;
if (snd_info_register(entry) < 0) { if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry); snd_info_free_entry(entry);
......
...@@ -41,12 +41,13 @@ MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_MIXER); ...@@ -41,12 +41,13 @@ MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_MIXER);
static int snd_mixer_oss_open(struct inode *inode, struct file *file) static int snd_mixer_oss_open(struct inode *inode, struct file *file)
{ {
int cardnum = SNDRV_MINOR_OSS_CARD(iminor(inode));
struct snd_card *card; struct snd_card *card;
struct snd_mixer_oss_file *fmixer; struct snd_mixer_oss_file *fmixer;
int err; int err;
if ((card = snd_cards[cardnum]) == NULL) card = snd_lookup_oss_minor_data(iminor(inode),
SNDRV_OSS_DEVICE_TYPE_MIXER);
if (card == NULL)
return -ENODEV; return -ENODEV;
if (card->mixer_oss == NULL) if (card->mixer_oss == NULL)
return -ENODEV; return -ENODEV;
...@@ -1286,7 +1287,7 @@ static int snd_mixer_oss_notify_handler(struct snd_card *card, int cmd) ...@@ -1286,7 +1287,7 @@ static int snd_mixer_oss_notify_handler(struct snd_card *card, int cmd)
sprintf(name, "mixer%i%i", card->number, 0); sprintf(name, "mixer%i%i", card->number, 0);
if ((err = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER, if ((err = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER,
card, 0, card, 0,
&snd_mixer_oss_f_ops, &snd_mixer_oss_f_ops, card,
name)) < 0) { name)) < 0) {
snd_printk(KERN_ERR "unable to register OSS mixer device %i:%i\n", snd_printk(KERN_ERR "unable to register OSS mixer device %i:%i\n",
card->number, 0); card->number, 0);
......
...@@ -1834,9 +1834,6 @@ static int snd_task_name(struct task_struct *task, char *name, size_t size) ...@@ -1834,9 +1834,6 @@ static int snd_task_name(struct task_struct *task, char *name, size_t size)
static int snd_pcm_oss_open(struct inode *inode, struct file *file) static int snd_pcm_oss_open(struct inode *inode, struct file *file)
{ {
int minor = iminor(inode);
int cardnum = SNDRV_MINOR_OSS_CARD(minor);
int device;
int err; int err;
char task_name[32]; char task_name[32];
struct snd_pcm *pcm; struct snd_pcm *pcm;
...@@ -1845,11 +1842,8 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) ...@@ -1845,11 +1842,8 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
int nonblock; int nonblock;
wait_queue_t wait; wait_queue_t wait;
snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO); pcm = snd_lookup_oss_minor_data(iminor(inode),
device = SNDRV_MINOR_OSS_DEVICE(minor) == SNDRV_MINOR_OSS_PCM1 ? SNDRV_OSS_DEVICE_TYPE_PCM);
adsp_map[cardnum] : dsp_map[cardnum];
pcm = snd_pcm_devices[(cardnum * SNDRV_PCM_DEVICES) + device];
if (pcm == NULL) { if (pcm == NULL) {
err = -ENODEV; err = -ENODEV;
goto __error1; goto __error1;
...@@ -1890,7 +1884,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) ...@@ -1890,7 +1884,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
down(&pcm->open_mutex); down(&pcm->open_mutex);
while (1) { while (1) {
err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file, err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file,
minor, psetup, csetup); iminor(inode), psetup, csetup);
if (err >= 0) if (err >= 0)
break; break;
if (err == -EAGAIN) { if (err == -EAGAIN) {
...@@ -2450,7 +2444,7 @@ static void register_oss_dsp(struct snd_pcm *pcm, int index) ...@@ -2450,7 +2444,7 @@ static void register_oss_dsp(struct snd_pcm *pcm, int index)
sprintf(name, "dsp%i%i", pcm->card->number, pcm->device); sprintf(name, "dsp%i%i", pcm->card->number, pcm->device);
if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM, if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,
pcm->card, index, &snd_pcm_oss_f_reg, pcm->card, index, &snd_pcm_oss_f_reg,
name) < 0) { pcm, name) < 0) {
snd_printk(KERN_ERR "unable to register OSS PCM device %i:%i\n", snd_printk(KERN_ERR "unable to register OSS PCM device %i:%i\n",
pcm->card->number, pcm->device); pcm->card->number, pcm->device);
} }
......
...@@ -33,7 +33,7 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Abramo Bagnara <abramo@alsa-proj ...@@ -33,7 +33,7 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Abramo Bagnara <abramo@alsa-proj
MODULE_DESCRIPTION("Midlevel PCM code for ALSA."); MODULE_DESCRIPTION("Midlevel PCM code for ALSA.");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
struct snd_pcm *snd_pcm_devices[SNDRV_CARDS * SNDRV_PCM_DEVICES]; static LIST_HEAD(snd_pcm_devices);
static LIST_HEAD(snd_pcm_notify_list); static LIST_HEAD(snd_pcm_notify_list);
static DECLARE_MUTEX(register_mutex); static DECLARE_MUTEX(register_mutex);
...@@ -43,13 +43,23 @@ static int snd_pcm_dev_register(struct snd_device *device); ...@@ -43,13 +43,23 @@ static int snd_pcm_dev_register(struct snd_device *device);
static int snd_pcm_dev_disconnect(struct snd_device *device); static int snd_pcm_dev_disconnect(struct snd_device *device);
static int snd_pcm_dev_unregister(struct snd_device *device); static int snd_pcm_dev_unregister(struct snd_device *device);
static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device)
{
struct list_head *p;
struct snd_pcm *pcm;
list_for_each(p, &snd_pcm_devices) {
pcm = list_entry(p, struct snd_pcm, list);
if (pcm->card == card && pcm->device == device)
return pcm;
}
return NULL;
}
static int snd_pcm_control_ioctl(struct snd_card *card, static int snd_pcm_control_ioctl(struct snd_card *card,
struct snd_ctl_file *control, struct snd_ctl_file *control,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
unsigned int tmp;
tmp = card->number * SNDRV_PCM_DEVICES;
switch (cmd) { switch (cmd) {
case SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE: case SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE:
{ {
...@@ -57,14 +67,16 @@ static int snd_pcm_control_ioctl(struct snd_card *card, ...@@ -57,14 +67,16 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
if (get_user(device, (int __user *)arg)) if (get_user(device, (int __user *)arg))
return -EFAULT; return -EFAULT;
down(&register_mutex);
device = device < 0 ? 0 : device + 1; device = device < 0 ? 0 : device + 1;
while (device < SNDRV_PCM_DEVICES) { while (device < SNDRV_PCM_DEVICES) {
if (snd_pcm_devices[tmp + device]) if (snd_pcm_search(card, device))
break; break;
device++; device++;
} }
if (device == SNDRV_PCM_DEVICES) if (device == SNDRV_PCM_DEVICES)
device = -1; device = -1;
up(&register_mutex);
if (put_user(device, (int __user *)arg)) if (put_user(device, (int __user *)arg))
return -EFAULT; return -EFAULT;
return 0; return 0;
...@@ -77,31 +89,44 @@ static int snd_pcm_control_ioctl(struct snd_card *card, ...@@ -77,31 +89,44 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
struct snd_pcm *pcm; struct snd_pcm *pcm;
struct snd_pcm_str *pstr; struct snd_pcm_str *pstr;
struct snd_pcm_substream *substream; struct snd_pcm_substream *substream;
int err;
info = (struct snd_pcm_info __user *)arg; info = (struct snd_pcm_info __user *)arg;
if (get_user(device, &info->device)) if (get_user(device, &info->device))
return -EFAULT; return -EFAULT;
if (device >= SNDRV_PCM_DEVICES)
return -ENXIO;
pcm = snd_pcm_devices[tmp + device];
if (pcm == NULL)
return -ENXIO;
if (get_user(stream, &info->stream)) if (get_user(stream, &info->stream))
return -EFAULT; return -EFAULT;
if (stream < 0 || stream > 1) if (stream < 0 || stream > 1)
return -EINVAL; return -EINVAL;
pstr = &pcm->streams[stream];
if (pstr->substream_count == 0)
return -ENOENT;
if (get_user(subdevice, &info->subdevice)) if (get_user(subdevice, &info->subdevice))
return -EFAULT; return -EFAULT;
if (subdevice >= pstr->substream_count) down(&register_mutex);
return -ENXIO; pcm = snd_pcm_search(card, device);
for (substream = pstr->substream; substream; substream = substream->next) if (pcm == NULL) {
err = -ENXIO;
goto _error;
}
pstr = &pcm->streams[stream];
if (pstr->substream_count == 0) {
err = -ENOENT;
goto _error;
}
if (subdevice >= pstr->substream_count) {
err = -ENXIO;
goto _error;
}
for (substream = pstr->substream; substream;
substream = substream->next)
if (substream->number == (int)subdevice) if (substream->number == (int)subdevice)
break; break;
if (substream == NULL) if (substream == NULL) {
return -ENXIO; err = -ENXIO;
return snd_pcm_info_user(substream, info); goto _error;
}
err = snd_pcm_info_user(substream, info);
_error:
up(&register_mutex);
return err;
} }
case SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE: case SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE:
{ {
...@@ -865,8 +890,7 @@ void snd_pcm_release_substream(struct snd_pcm_substream *substream) ...@@ -865,8 +890,7 @@ void snd_pcm_release_substream(struct snd_pcm_substream *substream)
static int snd_pcm_dev_register(struct snd_device *device) static int snd_pcm_dev_register(struct snd_device *device)
{ {
int idx, cidx, err; int cidx, err;
unsigned short minor;
struct snd_pcm_substream *substream; struct snd_pcm_substream *substream;
struct list_head *list; struct list_head *list;
char str[16]; char str[16];
...@@ -874,12 +898,11 @@ static int snd_pcm_dev_register(struct snd_device *device) ...@@ -874,12 +898,11 @@ static int snd_pcm_dev_register(struct snd_device *device)
snd_assert(pcm != NULL && device != NULL, return -ENXIO); snd_assert(pcm != NULL && device != NULL, return -ENXIO);
down(&register_mutex); down(&register_mutex);
idx = (pcm->card->number * SNDRV_PCM_DEVICES) + pcm->device; if (snd_pcm_search(pcm->card, pcm->device)) {
if (snd_pcm_devices[idx]) {
up(&register_mutex); up(&register_mutex);
return -EBUSY; return -EBUSY;
} }
snd_pcm_devices[idx] = pcm; list_add_tail(&pcm->list, &snd_pcm_devices);
for (cidx = 0; cidx < 2; cidx++) { for (cidx = 0; cidx < 2; cidx++) {
int devtype = -1; int devtype = -1;
if (pcm->streams[cidx].substream == NULL) if (pcm->streams[cidx].substream == NULL)
...@@ -887,20 +910,19 @@ static int snd_pcm_dev_register(struct snd_device *device) ...@@ -887,20 +910,19 @@ static int snd_pcm_dev_register(struct snd_device *device)
switch (cidx) { switch (cidx) {
case SNDRV_PCM_STREAM_PLAYBACK: case SNDRV_PCM_STREAM_PLAYBACK:
sprintf(str, "pcmC%iD%ip", pcm->card->number, pcm->device); sprintf(str, "pcmC%iD%ip", pcm->card->number, pcm->device);
minor = SNDRV_MINOR_PCM_PLAYBACK + idx;
devtype = SNDRV_DEVICE_TYPE_PCM_PLAYBACK; devtype = SNDRV_DEVICE_TYPE_PCM_PLAYBACK;
break; break;
case SNDRV_PCM_STREAM_CAPTURE: case SNDRV_PCM_STREAM_CAPTURE:
sprintf(str, "pcmC%iD%ic", pcm->card->number, pcm->device); sprintf(str, "pcmC%iD%ic", pcm->card->number, pcm->device);
minor = SNDRV_MINOR_PCM_CAPTURE + idx;
devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE; devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE;
break; break;
} }
if ((err = snd_register_device(devtype, pcm->card, if ((err = snd_register_device(devtype, pcm->card,
pcm->device, pcm->device,
&snd_pcm_f_ops[cidx], str)) < 0) &snd_pcm_f_ops[cidx],
pcm, str)) < 0)
{ {
snd_pcm_devices[idx] = NULL; list_del(&pcm->list);
up(&register_mutex); up(&register_mutex);
return err; return err;
} }
...@@ -921,11 +943,10 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) ...@@ -921,11 +943,10 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
struct snd_pcm *pcm = device->device_data; struct snd_pcm *pcm = device->device_data;
struct list_head *list; struct list_head *list;
struct snd_pcm_substream *substream; struct snd_pcm_substream *substream;
int idx, cidx; int cidx;
down(&register_mutex); down(&register_mutex);
idx = (pcm->card->number * SNDRV_PCM_DEVICES) + pcm->device; list_del_init(&pcm->list);
snd_pcm_devices[idx] = NULL;
for (cidx = 0; cidx < 2; cidx++) for (cidx = 0; cidx < 2; cidx++)
for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
if (substream->runtime) if (substream->runtime)
...@@ -941,15 +962,14 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) ...@@ -941,15 +962,14 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
static int snd_pcm_dev_unregister(struct snd_device *device) static int snd_pcm_dev_unregister(struct snd_device *device)
{ {
int idx, cidx, devtype; int cidx, devtype;
struct snd_pcm_substream *substream; struct snd_pcm_substream *substream;
struct list_head *list; struct list_head *list;
struct snd_pcm *pcm = device->device_data; struct snd_pcm *pcm = device->device_data;
snd_assert(pcm != NULL, return -ENXIO); snd_assert(pcm != NULL, return -ENXIO);
down(&register_mutex); down(&register_mutex);
idx = (pcm->card->number * SNDRV_PCM_DEVICES) + pcm->device; list_del(&pcm->list);
snd_pcm_devices[idx] = NULL;
for (cidx = 0; cidx < 2; cidx++) { for (cidx = 0; cidx < 2; cidx++) {
devtype = -1; devtype = -1;
switch (cidx) { switch (cidx) {
...@@ -975,24 +995,19 @@ static int snd_pcm_dev_unregister(struct snd_device *device) ...@@ -975,24 +995,19 @@ static int snd_pcm_dev_unregister(struct snd_device *device)
int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree) int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree)
{ {
int idx; struct list_head *p;
snd_assert(notify != NULL && notify->n_register != NULL && notify->n_unregister != NULL, return -EINVAL); snd_assert(notify != NULL && notify->n_register != NULL && notify->n_unregister != NULL, return -EINVAL);
down(&register_mutex); down(&register_mutex);
if (nfree) { if (nfree) {
list_del(&notify->list); list_del(&notify->list);
for (idx = 0; idx < SNDRV_CARDS * SNDRV_PCM_DEVICES; idx++) { list_for_each(p, &snd_pcm_devices)
if (snd_pcm_devices[idx] == NULL) notify->n_unregister(list_entry(p,
continue; struct snd_pcm, list));
notify->n_unregister(snd_pcm_devices[idx]);
}
} else { } else {
list_add_tail(&notify->list, &snd_pcm_notify_list); list_add_tail(&notify->list, &snd_pcm_notify_list);
for (idx = 0; idx < SNDRV_CARDS * SNDRV_PCM_DEVICES; idx++) { list_for_each(p, &snd_pcm_devices)
if (snd_pcm_devices[idx] == NULL) notify->n_register(list_entry(p, struct snd_pcm, list));
continue;
notify->n_register(snd_pcm_devices[idx]);
}
} }
up(&register_mutex); up(&register_mutex);
return 0; return 0;
...@@ -1005,16 +1020,14 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree) ...@@ -1005,16 +1020,14 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree)
static void snd_pcm_proc_read(struct snd_info_entry *entry, static void snd_pcm_proc_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer) struct snd_info_buffer *buffer)
{ {
int idx; struct list_head *p;
struct snd_pcm *pcm; struct snd_pcm *pcm;
down(&register_mutex); down(&register_mutex);
for (idx = 0; idx < SNDRV_CARDS * SNDRV_PCM_DEVICES; idx++) { list_for_each(p, &snd_pcm_devices) {
pcm = snd_pcm_devices[idx]; pcm = list_entry(p, struct snd_pcm, list);
if (pcm == NULL) snd_iprintf(buffer, "%02i-%02i: %s : %s",
continue; pcm->card->number, pcm->device, pcm->id, pcm->name);
snd_iprintf(buffer, "%02i-%02i: %s : %s", idx / SNDRV_PCM_DEVICES,
idx % SNDRV_PCM_DEVICES, pcm->id, pcm->name);
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
snd_iprintf(buffer, " : playback %i", snd_iprintf(buffer, " : playback %i",
pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count); pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count);
...@@ -1063,7 +1076,6 @@ static void __exit alsa_pcm_exit(void) ...@@ -1063,7 +1076,6 @@ static void __exit alsa_pcm_exit(void)
module_init(alsa_pcm_init) module_init(alsa_pcm_init)
module_exit(alsa_pcm_exit) module_exit(alsa_pcm_exit)
EXPORT_SYMBOL(snd_pcm_devices);
EXPORT_SYMBOL(snd_pcm_new); EXPORT_SYMBOL(snd_pcm_new);
EXPORT_SYMBOL(snd_pcm_new_stream); EXPORT_SYMBOL(snd_pcm_new_stream);
EXPORT_SYMBOL(snd_pcm_notify); EXPORT_SYMBOL(snd_pcm_notify);
......
...@@ -62,6 +62,7 @@ static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream, ...@@ -62,6 +62,7 @@ static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params_old __user * _oparams); struct snd_pcm_hw_params_old __user * _oparams);
static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream, static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params_old __user * _oparams); struct snd_pcm_hw_params_old __user * _oparams);
static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream);
/* /*
* *
...@@ -1554,7 +1555,8 @@ static struct file *snd_pcm_file_fd(int fd) ...@@ -1554,7 +1555,8 @@ static struct file *snd_pcm_file_fd(int fd)
{ {
struct file *file; struct file *file;
struct inode *inode; struct inode *inode;
unsigned short minor; unsigned int minor;
file = fget(fd); file = fget(fd);
if (!file) if (!file)
return NULL; return NULL;
...@@ -1565,8 +1567,8 @@ static struct file *snd_pcm_file_fd(int fd) ...@@ -1565,8 +1567,8 @@ static struct file *snd_pcm_file_fd(int fd)
return NULL; return NULL;
} }
minor = iminor(inode); minor = iminor(inode);
if (minor >= 256 || if (!snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_PLAYBACK) &&
minor % SNDRV_MINOR_DEVICES < SNDRV_MINOR_PCM_PLAYBACK) { !snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_CAPTURE)) {
fput(file); fput(file);
return NULL; return NULL;
} }
...@@ -2071,18 +2073,30 @@ static int snd_pcm_open_file(struct file *file, ...@@ -2071,18 +2073,30 @@ static int snd_pcm_open_file(struct file *file,
return 0; return 0;
} }
static int snd_pcm_open(struct inode *inode, struct file *file) static int snd_pcm_playback_open(struct inode *inode, struct file *file)
{
struct snd_pcm *pcm;
pcm = snd_lookup_minor_data(iminor(inode),
SNDRV_DEVICE_TYPE_PCM_PLAYBACK);
return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK);
}
static int snd_pcm_capture_open(struct inode *inode, struct file *file)
{ {
int cardnum = SNDRV_MINOR_CARD(iminor(inode));
int device = SNDRV_MINOR_DEVICE(iminor(inode));
int err;
struct snd_pcm *pcm; struct snd_pcm *pcm;
pcm = snd_lookup_minor_data(iminor(inode),
SNDRV_DEVICE_TYPE_PCM_CAPTURE);
return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE);
}
static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)
{
int err;
struct snd_pcm_file *pcm_file; struct snd_pcm_file *pcm_file;
wait_queue_t wait; wait_queue_t wait;
if (device < SNDRV_MINOR_PCM_PLAYBACK || device >= SNDRV_MINOR_DEVICES)
return -ENXIO;
pcm = snd_pcm_devices[(cardnum * SNDRV_PCM_DEVICES) + (device % SNDRV_MINOR_PCMS)];
if (pcm == NULL) { if (pcm == NULL) {
err = -ENODEV; err = -ENODEV;
goto __error1; goto __error1;
...@@ -2098,7 +2112,7 @@ static int snd_pcm_open(struct inode *inode, struct file *file) ...@@ -2098,7 +2112,7 @@ static int snd_pcm_open(struct inode *inode, struct file *file)
add_wait_queue(&pcm->open_wait, &wait); add_wait_queue(&pcm->open_wait, &wait);
down(&pcm->open_mutex); down(&pcm->open_mutex);
while (1) { while (1) {
err = snd_pcm_open_file(file, pcm, device >= SNDRV_MINOR_PCM_CAPTURE ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK, &pcm_file); err = snd_pcm_open_file(file, pcm, stream, &pcm_file);
if (err >= 0) if (err >= 0)
break; break;
if (err == -EAGAIN) { if (err == -EAGAIN) {
...@@ -3375,7 +3389,7 @@ struct file_operations snd_pcm_f_ops[2] = { ...@@ -3375,7 +3389,7 @@ struct file_operations snd_pcm_f_ops[2] = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.write = snd_pcm_write, .write = snd_pcm_write,
.writev = snd_pcm_writev, .writev = snd_pcm_writev,
.open = snd_pcm_open, .open = snd_pcm_playback_open,
.release = snd_pcm_release, .release = snd_pcm_release,
.poll = snd_pcm_playback_poll, .poll = snd_pcm_playback_poll,
.unlocked_ioctl = snd_pcm_playback_ioctl, .unlocked_ioctl = snd_pcm_playback_ioctl,
...@@ -3387,7 +3401,7 @@ struct file_operations snd_pcm_f_ops[2] = { ...@@ -3387,7 +3401,7 @@ struct file_operations snd_pcm_f_ops[2] = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.read = snd_pcm_read, .read = snd_pcm_read,
.readv = snd_pcm_readv, .readv = snd_pcm_readv,
.open = snd_pcm_open, .open = snd_pcm_capture_open,
.release = snd_pcm_release, .release = snd_pcm_release,
.poll = snd_pcm_capture_poll, .poll = snd_pcm_capture_poll,
.unlocked_ioctl = snd_pcm_capture_ioctl, .unlocked_ioctl = snd_pcm_capture_ioctl,
......
...@@ -56,10 +56,22 @@ static int snd_rawmidi_dev_register(struct snd_device *device); ...@@ -56,10 +56,22 @@ static int snd_rawmidi_dev_register(struct snd_device *device);
static int snd_rawmidi_dev_disconnect(struct snd_device *device); static int snd_rawmidi_dev_disconnect(struct snd_device *device);
static int snd_rawmidi_dev_unregister(struct snd_device *device); static int snd_rawmidi_dev_unregister(struct snd_device *device);
static struct snd_rawmidi *snd_rawmidi_devices[SNDRV_CARDS * SNDRV_RAWMIDI_DEVICES]; static LIST_HEAD(snd_rawmidi_devices);
static DECLARE_MUTEX(register_mutex); static DECLARE_MUTEX(register_mutex);
static struct snd_rawmidi *snd_rawmidi_search(struct snd_card *card, int device)
{
struct list_head *p;
struct snd_rawmidi *rawmidi;
list_for_each(p, &snd_rawmidi_devices) {
rawmidi = list_entry(p, struct snd_rawmidi, list);
if (rawmidi->card == card && rawmidi->device == device)
return rawmidi;
}
return NULL;
}
static inline unsigned short snd_rawmidi_file_flags(struct file *file) static inline unsigned short snd_rawmidi_file_flags(struct file *file)
{ {
switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) { switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) {
...@@ -214,7 +226,7 @@ int snd_rawmidi_drain_input(struct snd_rawmidi_substream *substream) ...@@ -214,7 +226,7 @@ int snd_rawmidi_drain_input(struct snd_rawmidi_substream *substream)
return 0; return 0;
} }
int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice, int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice,
int mode, struct snd_rawmidi_file * rfile) int mode, struct snd_rawmidi_file * rfile)
{ {
struct snd_rawmidi *rmidi; struct snd_rawmidi *rmidi;
...@@ -225,7 +237,9 @@ int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice, ...@@ -225,7 +237,9 @@ int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice,
if (rfile) if (rfile)
rfile->input = rfile->output = NULL; rfile->input = rfile->output = NULL;
rmidi = snd_rawmidi_devices[(cardnum * SNDRV_RAWMIDI_DEVICES) + device]; down(&register_mutex);
rmidi = snd_rawmidi_search(card, device);
up(&register_mutex);
if (rmidi == NULL) { if (rmidi == NULL) {
err = -ENODEV; err = -ENODEV;
goto __error1; goto __error1;
...@@ -368,9 +382,8 @@ int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice, ...@@ -368,9 +382,8 @@ int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice,
static int snd_rawmidi_open(struct inode *inode, struct file *file) static int snd_rawmidi_open(struct inode *inode, struct file *file)
{ {
int maj = imajor(inode); int maj = imajor(inode);
int cardnum;
struct snd_card *card; struct snd_card *card;
int device, subdevice; int subdevice;
unsigned short fflags; unsigned short fflags;
int err; int err;
struct snd_rawmidi *rmidi; struct snd_rawmidi *rmidi;
...@@ -380,27 +393,18 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) ...@@ -380,27 +393,18 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
struct snd_ctl_file *kctl; struct snd_ctl_file *kctl;
if (maj == snd_major) { if (maj == snd_major) {
cardnum = SNDRV_MINOR_CARD(iminor(inode)); rmidi = snd_lookup_minor_data(iminor(inode),
cardnum %= SNDRV_CARDS; SNDRV_DEVICE_TYPE_RAWMIDI);
device = SNDRV_MINOR_DEVICE(iminor(inode)) - SNDRV_MINOR_RAWMIDI;
device %= SNDRV_MINOR_RAWMIDIS;
#ifdef CONFIG_SND_OSSEMUL #ifdef CONFIG_SND_OSSEMUL
} else if (maj == SOUND_MAJOR) { } else if (maj == SOUND_MAJOR) {
cardnum = SNDRV_MINOR_OSS_CARD(iminor(inode)); rmidi = snd_lookup_oss_minor_data(iminor(inode),
cardnum %= SNDRV_CARDS; SNDRV_OSS_DEVICE_TYPE_MIDI);
device = SNDRV_MINOR_OSS_DEVICE(iminor(inode)) == SNDRV_MINOR_OSS_MIDI ?
midi_map[cardnum] : amidi_map[cardnum];
#endif #endif
} else } else
return -ENXIO; return -ENXIO;
rmidi = snd_rawmidi_devices[(cardnum * SNDRV_RAWMIDI_DEVICES) + device];
if (rmidi == NULL) if (rmidi == NULL)
return -ENODEV; return -ENODEV;
#ifdef CONFIG_SND_OSSEMUL
if (maj == SOUND_MAJOR && !rmidi->ossreg)
return -ENXIO;
#endif
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 */
card = rmidi->card; card = rmidi->card;
...@@ -430,7 +434,8 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) ...@@ -430,7 +434,8 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
} }
} }
up_read(&card->controls_rwsem); up_read(&card->controls_rwsem);
err = snd_rawmidi_kernel_open(cardnum, device, subdevice, fflags, rawmidi_file); err = snd_rawmidi_kernel_open(rmidi->card, rmidi->device,
subdevice, fflags, rawmidi_file);
if (err >= 0) if (err >= 0)
break; break;
if (err == -EAGAIN) { if (err == -EAGAIN) {
...@@ -570,9 +575,10 @@ int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info ...@@ -570,9 +575,10 @@ int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info
struct snd_rawmidi_str *pstr; struct snd_rawmidi_str *pstr;
struct snd_rawmidi_substream *substream; struct snd_rawmidi_substream *substream;
struct list_head *list; struct list_head *list;
if (info->device >= SNDRV_RAWMIDI_DEVICES)
return -ENXIO; down(&register_mutex);
rmidi = snd_rawmidi_devices[card->number * SNDRV_RAWMIDI_DEVICES + info->device]; rmidi = snd_rawmidi_search(card, info->device);
up(&register_mutex);
if (!rmidi) if (!rmidi)
return -ENXIO; return -ENXIO;
if (info->stream < 0 || info->stream > 1) if (info->stream < 0 || info->stream > 1)
...@@ -803,9 +809,7 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card, ...@@ -803,9 +809,7 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card,
unsigned long arg) unsigned long arg)
{ {
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
unsigned int tmp;
tmp = card->number * SNDRV_RAWMIDI_DEVICES;
switch (cmd) { switch (cmd) {
case SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE: case SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE:
{ {
...@@ -813,14 +817,16 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card, ...@@ -813,14 +817,16 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card,
if (get_user(device, (int __user *)argp)) if (get_user(device, (int __user *)argp))
return -EFAULT; return -EFAULT;
down(&register_mutex);
device = device < 0 ? 0 : device + 1; device = device < 0 ? 0 : device + 1;
while (device < SNDRV_RAWMIDI_DEVICES) { while (device < SNDRV_RAWMIDI_DEVICES) {
if (snd_rawmidi_devices[tmp + device]) if (snd_rawmidi_search(card, device))
break; break;
device++; device++;
} }
if (device == SNDRV_RAWMIDI_DEVICES) if (device == SNDRV_RAWMIDI_DEVICES)
device = -1; device = -1;
up(&register_mutex);
if (put_user(device, (int __user *)argp)) if (put_user(device, (int __user *)argp))
return -EFAULT; return -EFAULT;
return 0; return 0;
...@@ -1493,7 +1499,7 @@ static void snd_rawmidi_dev_seq_free(struct snd_seq_device *device) ...@@ -1493,7 +1499,7 @@ static void snd_rawmidi_dev_seq_free(struct snd_seq_device *device)
static int snd_rawmidi_dev_register(struct snd_device *device) static int snd_rawmidi_dev_register(struct snd_device *device)
{ {
int idx, err; int err;
struct snd_info_entry *entry; struct snd_info_entry *entry;
char name[16]; char name[16];
struct snd_rawmidi *rmidi = device->device_data; struct snd_rawmidi *rmidi = device->device_data;
...@@ -1501,25 +1507,24 @@ static int snd_rawmidi_dev_register(struct snd_device *device) ...@@ -1501,25 +1507,24 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
if (rmidi->device >= SNDRV_RAWMIDI_DEVICES) if (rmidi->device >= SNDRV_RAWMIDI_DEVICES)
return -ENOMEM; return -ENOMEM;
down(&register_mutex); down(&register_mutex);
idx = (rmidi->card->number * SNDRV_RAWMIDI_DEVICES) + rmidi->device; if (snd_rawmidi_search(rmidi->card, rmidi->device)) {
if (snd_rawmidi_devices[idx] != NULL) {
up(&register_mutex); up(&register_mutex);
return -EBUSY; return -EBUSY;
} }
snd_rawmidi_devices[idx] = rmidi; list_add_tail(&rmidi->list, &snd_rawmidi_devices);
sprintf(name, "midiC%iD%i", rmidi->card->number, rmidi->device); sprintf(name, "midiC%iD%i", rmidi->card->number, rmidi->device);
if ((err = snd_register_device(SNDRV_DEVICE_TYPE_RAWMIDI, if ((err = snd_register_device(SNDRV_DEVICE_TYPE_RAWMIDI,
rmidi->card, rmidi->device, rmidi->card, rmidi->device,
&snd_rawmidi_f_ops, name)) < 0) { &snd_rawmidi_f_ops, rmidi, name)) < 0) {
snd_printk(KERN_ERR "unable to register rawmidi device %i:%i\n", rmidi->card->number, rmidi->device); snd_printk(KERN_ERR "unable to register rawmidi device %i:%i\n", rmidi->card->number, rmidi->device);
snd_rawmidi_devices[idx] = NULL; list_del(&rmidi->list);
up(&register_mutex); up(&register_mutex);
return err; return err;
} }
if (rmidi->ops && rmidi->ops->dev_register && if (rmidi->ops && rmidi->ops->dev_register &&
(err = rmidi->ops->dev_register(rmidi)) < 0) { (err = rmidi->ops->dev_register(rmidi)) < 0) {
snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device); snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device);
snd_rawmidi_devices[idx] = NULL; list_del(&rmidi->list);
up(&register_mutex); up(&register_mutex);
return err; return err;
} }
...@@ -1527,8 +1532,8 @@ static int snd_rawmidi_dev_register(struct snd_device *device) ...@@ -1527,8 +1532,8 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
rmidi->ossreg = 0; rmidi->ossreg = 0;
if ((int)rmidi->device == midi_map[rmidi->card->number]) { if ((int)rmidi->device == midi_map[rmidi->card->number]) {
if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI, if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI,
rmidi->card, 0, rmidi->card, 0, &snd_rawmidi_f_ops,
&snd_rawmidi_f_ops, name) < 0) { rmidi, name) < 0) {
snd_printk(KERN_ERR "unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 0); snd_printk(KERN_ERR "unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 0);
} else { } else {
rmidi->ossreg++; rmidi->ossreg++;
...@@ -1539,8 +1544,8 @@ static int snd_rawmidi_dev_register(struct snd_device *device) ...@@ -1539,8 +1544,8 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
} }
if ((int)rmidi->device == amidi_map[rmidi->card->number]) { if ((int)rmidi->device == amidi_map[rmidi->card->number]) {
if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI, if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI,
rmidi->card, 1, rmidi->card, 1, &snd_rawmidi_f_ops,
&snd_rawmidi_f_ops, name) < 0) { rmidi, name) < 0) {
snd_printk(KERN_ERR "unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 1); snd_printk(KERN_ERR "unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 1);
} else { } else {
rmidi->ossreg++; rmidi->ossreg++;
...@@ -1576,24 +1581,20 @@ static int snd_rawmidi_dev_register(struct snd_device *device) ...@@ -1576,24 +1581,20 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
static int snd_rawmidi_dev_disconnect(struct snd_device *device) static int snd_rawmidi_dev_disconnect(struct snd_device *device)
{ {
struct snd_rawmidi *rmidi = device->device_data; struct snd_rawmidi *rmidi = device->device_data;
int idx;
down(&register_mutex); down(&register_mutex);
idx = (rmidi->card->number * SNDRV_RAWMIDI_DEVICES) + rmidi->device; list_del_init(&rmidi->list);
snd_rawmidi_devices[idx] = NULL;
up(&register_mutex); up(&register_mutex);
return 0; return 0;
} }
static int snd_rawmidi_dev_unregister(struct snd_device *device) static int snd_rawmidi_dev_unregister(struct snd_device *device)
{ {
int idx;
struct snd_rawmidi *rmidi = device->device_data; struct snd_rawmidi *rmidi = device->device_data;
snd_assert(rmidi != NULL, return -ENXIO); snd_assert(rmidi != NULL, return -ENXIO);
down(&register_mutex); down(&register_mutex);
idx = (rmidi->card->number * SNDRV_RAWMIDI_DEVICES) + rmidi->device; list_del(&rmidi->list);
snd_rawmidi_devices[idx] = NULL;
if (rmidi->proc_entry) { if (rmidi->proc_entry) {
snd_info_unregister(rmidi->proc_entry); snd_info_unregister(rmidi->proc_entry);
rmidi->proc_entry = NULL; rmidi->proc_entry = NULL;
......
...@@ -225,7 +225,7 @@ register_device(void) ...@@ -225,7 +225,7 @@ register_device(void)
down(&register_mutex); down(&register_mutex);
if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER,
NULL, 0, NULL, 0,
&seq_oss_f_ops, &seq_oss_f_ops, NULL,
SNDRV_SEQ_OSS_DEVNAME)) < 0) { SNDRV_SEQ_OSS_DEVNAME)) < 0) {
snd_printk(KERN_ERR "can't register device seq\n"); snd_printk(KERN_ERR "can't register device seq\n");
up(&register_mutex); up(&register_mutex);
...@@ -233,7 +233,7 @@ register_device(void) ...@@ -233,7 +233,7 @@ register_device(void)
} }
if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC, if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC,
NULL, 0, NULL, 0,
&seq_oss_f_ops, &seq_oss_f_ops, NULL,
SNDRV_SEQ_OSS_DEVNAME)) < 0) { SNDRV_SEQ_OSS_DEVNAME)) < 0) {
snd_printk(KERN_ERR "can't register device music\n"); snd_printk(KERN_ERR "can't register device music\n");
snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0); snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0);
......
...@@ -2531,7 +2531,7 @@ int __init snd_sequencer_device_init(void) ...@@ -2531,7 +2531,7 @@ int __init snd_sequencer_device_init(void)
return -ERESTARTSYS; return -ERESTARTSYS;
if ((err = snd_register_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0, if ((err = snd_register_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0,
&snd_seq_f_ops, "seq")) < 0) { &snd_seq_f_ops, NULL, "seq")) < 0) {
up(&register_mutex); up(&register_mutex);
return err; return err;
} }
......
...@@ -183,7 +183,10 @@ static int midisynth_subscribe(void *private_data, struct snd_seq_port_subscribe ...@@ -183,7 +183,10 @@ static int midisynth_subscribe(void *private_data, struct snd_seq_port_subscribe
struct snd_rawmidi_params params; struct snd_rawmidi_params params;
/* open midi port */ /* open midi port */
if ((err = snd_rawmidi_kernel_open(msynth->card->number, msynth->device, msynth->subdevice, SNDRV_RAWMIDI_LFLG_INPUT, &msynth->input_rfile)) < 0) { if ((err = snd_rawmidi_kernel_open(msynth->card, msynth->device,
msynth->subdevice,
SNDRV_RAWMIDI_LFLG_INPUT,
&msynth->input_rfile)) < 0) {
snd_printd("midi input open failed!!!\n"); snd_printd("midi input open failed!!!\n");
return err; return err;
} }
...@@ -221,7 +224,10 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info ...@@ -221,7 +224,10 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info
struct snd_rawmidi_params params; struct snd_rawmidi_params params;
/* open midi port */ /* open midi port */
if ((err = snd_rawmidi_kernel_open(msynth->card->number, msynth->device, msynth->subdevice, SNDRV_RAWMIDI_LFLG_OUTPUT, &msynth->output_rfile)) < 0) { if ((err = snd_rawmidi_kernel_open(msynth->card, msynth->device,
msynth->subdevice,
SNDRV_RAWMIDI_LFLG_OUTPUT,
&msynth->output_rfile)) < 0) {
snd_printd("midi output open failed!!!\n"); snd_printd("midi output open failed!!!\n");
return err; return err;
} }
......
...@@ -60,7 +60,6 @@ MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR); ...@@ -60,7 +60,6 @@ MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR);
int snd_ecards_limit; int snd_ecards_limit;
static struct snd_minor *snd_minors[SNDRV_OS_MINORS]; static struct snd_minor *snd_minors[SNDRV_OS_MINORS];
static DECLARE_MUTEX(sound_mutex); static DECLARE_MUTEX(sound_mutex);
extern struct class *sound_class; extern struct class *sound_class;
...@@ -107,6 +106,31 @@ static void snd_request_other(int minor) ...@@ -107,6 +106,31 @@ static void snd_request_other(int minor)
#endif /* request_module support */ #endif /* request_module support */
/**
* snd_lookup_minor_data - get user data of a registered device
* @minor: the minor number
* @type: device type (SNDRV_DEVICE_TYPE_XXX)
*
* Checks that a minor device with the specified type is registered, and returns
* its user data pointer.
*/
void *snd_lookup_minor_data(unsigned int minor, int type)
{
struct snd_minor *mreg;
void *private_data;
if (minor > ARRAY_SIZE(snd_minors))
return NULL;
down(&sound_mutex);
mreg = snd_minors[minor];
if (mreg && mreg->type == type)
private_data = mreg->private_data;
else
private_data = NULL;
up(&sound_mutex);
return private_data;
}
static int snd_open(struct inode *inode, struct file *file) static int snd_open(struct inode *inode, struct file *file)
{ {
int minor = iminor(inode); int minor = iminor(inode);
...@@ -183,6 +207,7 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev) ...@@ -183,6 +207,7 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev)
* @card: the card instance * @card: the card instance
* @dev: the device index * @dev: the device index
* @f_ops: the file operations * @f_ops: the file operations
* @private_data: user pointer for f_ops->open()
* @name: the device file name * @name: the device file name
* *
* Registers an ALSA device file for the given card. * Registers an ALSA device file for the given card.
...@@ -191,7 +216,8 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev) ...@@ -191,7 +216,8 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev)
* Retrurns zero if successful, or a negative error code on failure. * Retrurns zero if successful, or a negative error code on failure.
*/ */
int snd_register_device(int type, struct snd_card *card, int dev, int snd_register_device(int type, struct snd_card *card, int dev,
struct file_operations *f_ops, const char *name) struct file_operations *f_ops, void *private_data,
const char *name)
{ {
int minor = snd_kernel_minor(type, card, dev); int minor = snd_kernel_minor(type, card, dev);
struct snd_minor *preg; struct snd_minor *preg;
...@@ -207,6 +233,7 @@ int snd_register_device(int type, struct snd_card *card, int dev, ...@@ -207,6 +233,7 @@ int snd_register_device(int type, struct snd_card *card, int dev,
preg->card = card ? card->number : -1; preg->card = card ? card->number : -1;
preg->device = dev; preg->device = dev;
preg->f_ops = f_ops; preg->f_ops = f_ops;
preg->private_data = private_data;
strcpy(preg->name, name); strcpy(preg->name, name);
down(&sound_mutex); down(&sound_mutex);
if (snd_minors[minor]) { if (snd_minors[minor]) {
...@@ -238,13 +265,18 @@ int snd_register_device(int type, struct snd_card *card, int dev, ...@@ -238,13 +265,18 @@ int snd_register_device(int type, struct snd_card *card, int dev,
*/ */
int snd_unregister_device(int type, struct snd_card *card, int dev) int snd_unregister_device(int type, struct snd_card *card, int dev)
{ {
int minor = snd_kernel_minor(type, card, dev); int cardnum, minor;
struct snd_minor *mptr; struct snd_minor *mptr;
if (minor < 0) cardnum = card ? card->number : -1;
return minor;
down(&sound_mutex); down(&sound_mutex);
if ((mptr = snd_minors[minor]) == NULL) { for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor)
if ((mptr = snd_minors[minor]) != NULL &&
mptr->type == type &&
mptr->card == cardnum &&
mptr->device == dev)
break;
if (minor == ARRAY_SIZE(snd_minors)) {
up(&sound_mutex); up(&sound_mutex);
return -EINVAL; return -EINVAL;
} }
...@@ -392,9 +424,11 @@ EXPORT_SYMBOL(snd_request_card); ...@@ -392,9 +424,11 @@ EXPORT_SYMBOL(snd_request_card);
#endif #endif
EXPORT_SYMBOL(snd_register_device); EXPORT_SYMBOL(snd_register_device);
EXPORT_SYMBOL(snd_unregister_device); EXPORT_SYMBOL(snd_unregister_device);
EXPORT_SYMBOL(snd_lookup_minor_data);
#if defined(CONFIG_SND_OSSEMUL) #if defined(CONFIG_SND_OSSEMUL)
EXPORT_SYMBOL(snd_register_oss_device); EXPORT_SYMBOL(snd_register_oss_device);
EXPORT_SYMBOL(snd_unregister_oss_device); EXPORT_SYMBOL(snd_unregister_oss_device);
EXPORT_SYMBOL(snd_lookup_oss_minor_data);
#endif #endif
/* memory.c */ /* memory.c */
EXPORT_SYMBOL(copy_to_user_fromio); EXPORT_SYMBOL(copy_to_user_fromio);
......
...@@ -38,9 +38,25 @@ ...@@ -38,9 +38,25 @@
#define SNDRV_OSS_MINORS 128 #define SNDRV_OSS_MINORS 128
static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS]; static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS];
static DECLARE_MUTEX(sound_oss_mutex); static DECLARE_MUTEX(sound_oss_mutex);
void *snd_lookup_oss_minor_data(unsigned int minor, int type)
{
struct snd_minor *mreg;
void *private_data;
if (minor > ARRAY_SIZE(snd_oss_minors))
return NULL;
down(&sound_oss_mutex);
mreg = snd_oss_minors[minor];
if (mreg && mreg->type == type)
private_data = mreg->private_data;
else
private_data = NULL;
up(&sound_oss_mutex);
return private_data;
}
static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev) static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev)
{ {
int minor; int minor;
...@@ -78,7 +94,8 @@ static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev) ...@@ -78,7 +94,8 @@ static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev)
} }
int snd_register_oss_device(int type, struct snd_card *card, int dev, int snd_register_oss_device(int type, struct snd_card *card, int dev,
struct file_operations *f_ops, const char *name) struct file_operations *f_ops, void *private_data,
const char *name)
{ {
int minor = snd_oss_kernel_minor(type, card, dev); int minor = snd_oss_kernel_minor(type, card, dev);
int minor_unit; int minor_unit;
...@@ -97,6 +114,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev, ...@@ -97,6 +114,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,
preg->card = card ? card->number : -1; preg->card = card ? card->number : -1;
preg->device = dev; preg->device = dev;
preg->f_ops = f_ops; preg->f_ops = f_ops;
preg->private_data = private_data;
down(&sound_oss_mutex); down(&sound_oss_mutex);
snd_oss_minors[minor] = preg; snd_oss_minors[minor] = preg;
minor_unit = SNDRV_MINOR_OSS_DEVICE(minor); minor_unit = SNDRV_MINOR_OSS_DEVICE(minor);
...@@ -121,6 +139,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev, ...@@ -121,6 +139,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,
carddev); carddev);
if (register2 != track2) if (register2 != track2)
goto __end; goto __end;
snd_oss_minors[track2] = preg;
} }
up(&sound_oss_mutex); up(&sound_oss_mutex);
return 0; return 0;
...@@ -163,8 +182,10 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev) ...@@ -163,8 +182,10 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev)
track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI1); track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI1);
break; break;
} }
if (track2 >= 0) if (track2 >= 0) {
unregister_sound_special(track2); unregister_sound_special(track2);
snd_oss_minors[track2] = NULL;
}
snd_oss_minors[minor] = NULL; snd_oss_minors[minor] = NULL;
up(&sound_oss_mutex); up(&sound_oss_mutex);
kfree(mptr); kfree(mptr);
......
...@@ -1952,8 +1952,8 @@ static int __init alsa_timer_init(void) ...@@ -1952,8 +1952,8 @@ static int __init alsa_timer_init(void)
if ((err = snd_timer_register_system()) < 0) if ((err = snd_timer_register_system()) < 0)
snd_printk(KERN_ERR "unable to register system timer (%i)\n", snd_printk(KERN_ERR "unable to register system timer (%i)\n",
err); err);
if ((err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER, if ((err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER, NULL, 0,
NULL, 0, &snd_timer_f_ops, "timer")) < 0) &snd_timer_f_ops, NULL, "timer")) < 0)
snd_printk(KERN_ERR "unable to register timer device (%i)\n", snd_printk(KERN_ERR "unable to register timer device (%i)\n",
err); err);
return 0; return 0;
......
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