[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: Clemens Ladisch <clemens@ladisch.de>
This commit is contained in:
parent
6983b7240c
commit
f87135f56c
17 changed files with 278 additions and 197 deletions
|
@ -187,6 +187,7 @@ struct snd_minor {
|
|||
int card; /* card number */
|
||||
int device; /* device number */
|
||||
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
|
||||
structure) */
|
||||
};
|
||||
|
@ -199,13 +200,17 @@ extern int snd_ecards_limit;
|
|||
void snd_request_card(int card);
|
||||
|
||||
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);
|
||||
void *snd_lookup_minor_data(unsigned int minor, int type);
|
||||
|
||||
#ifdef CONFIG_SND_OSSEMUL
|
||||
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);
|
||||
void *snd_lookup_oss_minor_data(unsigned int minor, int type);
|
||||
#endif
|
||||
|
||||
int snd_minor_info_init(void);
|
||||
|
|
|
@ -43,6 +43,7 @@ struct snd_hwdep_ops {
|
|||
|
||||
struct snd_hwdep {
|
||||
struct snd_card *card;
|
||||
struct list_head list;
|
||||
int device;
|
||||
char id[32];
|
||||
char name[80];
|
||||
|
|
|
@ -412,6 +412,7 @@ struct snd_pcm_str {
|
|||
|
||||
struct snd_pcm {
|
||||
struct snd_card *card;
|
||||
struct list_head list;
|
||||
unsigned int device; /* device number */
|
||||
unsigned int info_flags;
|
||||
unsigned short dev_class;
|
||||
|
@ -439,7 +440,6 @@ struct snd_pcm_notify {
|
|||
* Registering
|
||||
*/
|
||||
|
||||
extern struct snd_pcm *snd_pcm_devices[];
|
||||
extern struct file_operations snd_pcm_f_ops[2];
|
||||
|
||||
int snd_pcm_new(struct snd_card *card, char *id, int device,
|
||||
|
|
|
@ -113,7 +113,7 @@ struct snd_rawmidi_str {
|
|||
|
||||
struct snd_rawmidi {
|
||||
struct snd_card *card;
|
||||
|
||||
struct list_head list;
|
||||
unsigned int device; /* device number */
|
||||
unsigned int info_flags; /* SNDRV_RAWMIDI_INFO_XXXX */
|
||||
char id[64];
|
||||
|
@ -165,8 +165,8 @@ int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,
|
|||
/* main midi functions */
|
||||
|
||||
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,
|
||||
struct snd_rawmidi_file *rfile);
|
||||
int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice,
|
||||
int mode, 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,
|
||||
struct snd_rawmidi_params *params);
|
||||
|
|
|
@ -47,13 +47,12 @@ static LIST_HEAD(snd_control_compat_ioctls);
|
|||
|
||||
static int snd_ctl_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
int cardnum = SNDRV_MINOR_CARD(iminor(inode));
|
||||
unsigned long flags;
|
||||
struct snd_card *card;
|
||||
struct snd_ctl_file *ctl;
|
||||
int err;
|
||||
|
||||
card = snd_cards[cardnum];
|
||||
card = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_CONTROL);
|
||||
if (!card) {
|
||||
err = -ENODEV;
|
||||
goto __error1;
|
||||
|
@ -1277,8 +1276,8 @@ static int snd_ctl_dev_register(struct snd_device *device)
|
|||
cardnum = card->number;
|
||||
snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO);
|
||||
sprintf(name, "controlC%i", cardnum);
|
||||
if ((err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL,
|
||||
card, -1, &snd_ctl_f_ops, name)) < 0)
|
||||
if ((err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1,
|
||||
&snd_ctl_f_ops, card, name)) < 0)
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -35,8 +35,7 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
|
|||
MODULE_DESCRIPTION("Hardware dependent layer");
|
||||
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 int snd_hwdep_free(struct snd_hwdep *hwdep);
|
||||
|
@ -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_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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
int major = imajor(inode);
|
||||
int cardnum;
|
||||
int device;
|
||||
struct snd_hwdep *hw;
|
||||
int err;
|
||||
wait_queue_t wait;
|
||||
|
||||
if (major == snd_major) {
|
||||
cardnum = SNDRV_MINOR_CARD(iminor(inode));
|
||||
device = SNDRV_MINOR_DEVICE(iminor(inode)) - SNDRV_MINOR_HWDEP;
|
||||
hw = snd_lookup_minor_data(iminor(inode),
|
||||
SNDRV_DEVICE_TYPE_HWDEP);
|
||||
#ifdef CONFIG_SND_OSSEMUL
|
||||
} else if (major == SOUND_MAJOR) {
|
||||
cardnum = SNDRV_MINOR_OSS_CARD(iminor(inode));
|
||||
device = 0;
|
||||
hw = snd_lookup_oss_minor_data(iminor(inode),
|
||||
SNDRV_OSS_DEVICE_TYPE_DMFM);
|
||||
#endif
|
||||
} else
|
||||
return -ENXIO;
|
||||
cardnum %= SNDRV_CARDS;
|
||||
device %= SNDRV_MINOR_HWDEPS;
|
||||
hw = snd_hwdep_devices[(cardnum * SNDRV_MINOR_HWDEPS) + device];
|
||||
if (hw == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
if (!hw->ops.open)
|
||||
return -ENXIO;
|
||||
#ifdef CONFIG_SND_OSSEMUL
|
||||
if (major == SOUND_MAJOR && hw->oss_type < 0)
|
||||
return -ENXIO;
|
||||
#endif
|
||||
|
||||
if (!try_module_get(hw->card->module))
|
||||
return -EFAULT;
|
||||
|
@ -265,9 +265,6 @@ static int snd_hwdep_control_ioctl(struct snd_card *card,
|
|||
struct snd_ctl_file * control,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
unsigned int tmp;
|
||||
|
||||
tmp = card->number * SNDRV_MINOR_HWDEPS;
|
||||
switch (cmd) {
|
||||
case SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE:
|
||||
{
|
||||
|
@ -275,14 +272,16 @@ static int snd_hwdep_control_ioctl(struct snd_card *card,
|
|||
|
||||
if (get_user(device, (int __user *)arg))
|
||||
return -EFAULT;
|
||||
down(®ister_mutex);
|
||||
device = device < 0 ? 0 : device + 1;
|
||||
while (device < SNDRV_MINOR_HWDEPS) {
|
||||
if (snd_hwdep_devices[tmp + device])
|
||||
if (snd_hwdep_search(card, device))
|
||||
break;
|
||||
device++;
|
||||
}
|
||||
if (device >= SNDRV_MINOR_HWDEPS)
|
||||
device = -1;
|
||||
up(®ister_mutex);
|
||||
if (put_user(device, (int __user *)arg))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
@ -290,17 +289,19 @@ static int snd_hwdep_control_ioctl(struct snd_card *card,
|
|||
case SNDRV_CTL_IOCTL_HWDEP_INFO:
|
||||
{
|
||||
struct snd_hwdep_info __user *info = (struct snd_hwdep_info __user *)arg;
|
||||
int device;
|
||||
int device, err;
|
||||
struct snd_hwdep *hwdep;
|
||||
|
||||
if (get_user(device, &info->device))
|
||||
return -EFAULT;
|
||||
if (device < 0 || device >= SNDRV_MINOR_HWDEPS)
|
||||
return -ENXIO;
|
||||
hwdep = snd_hwdep_devices[tmp + device];
|
||||
if (hwdep == NULL)
|
||||
return -ENXIO;
|
||||
return snd_hwdep_info(hwdep, info);
|
||||
down(®ister_mutex);
|
||||
hwdep = snd_hwdep_search(card, device);
|
||||
if (hwdep)
|
||||
err = snd_hwdep_info(hwdep, info);
|
||||
else
|
||||
err = -ENXIO;
|
||||
up(®ister_mutex);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
return -ENOIOCTLCMD;
|
||||
|
@ -397,23 +398,22 @@ static int snd_hwdep_dev_free(struct snd_device *device)
|
|||
static int snd_hwdep_dev_register(struct snd_device *device)
|
||||
{
|
||||
struct snd_hwdep *hwdep = device->device_data;
|
||||
int idx, err;
|
||||
int err;
|
||||
char name[32];
|
||||
|
||||
down(®ister_mutex);
|
||||
idx = (hwdep->card->number * SNDRV_MINOR_HWDEPS) + hwdep->device;
|
||||
if (snd_hwdep_devices[idx]) {
|
||||
if (snd_hwdep_search(hwdep->card, hwdep->device)) {
|
||||
up(®ister_mutex);
|
||||
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);
|
||||
if ((err = snd_register_device(SNDRV_DEVICE_TYPE_HWDEP,
|
||||
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",
|
||||
hwdep->card->number, hwdep->device);
|
||||
snd_hwdep_devices[idx] = NULL;
|
||||
list_del(&hwdep->list);
|
||||
up(®ister_mutex);
|
||||
return err;
|
||||
}
|
||||
|
@ -425,7 +425,7 @@ static int snd_hwdep_dev_register(struct snd_device *device)
|
|||
} else {
|
||||
if (snd_register_oss_device(hwdep->oss_type,
|
||||
hwdep->card, hwdep->device,
|
||||
&snd_hwdep_f_ops,
|
||||
&snd_hwdep_f_ops, hwdep,
|
||||
hwdep->oss_dev) < 0) {
|
||||
snd_printk(KERN_ERR "unable to register OSS compatibility device %i:%i\n",
|
||||
hwdep->card->number, hwdep->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)
|
||||
{
|
||||
struct snd_hwdep *hwdep = device->device_data;
|
||||
int idx;
|
||||
|
||||
snd_assert(hwdep != NULL, return -ENXIO);
|
||||
down(®ister_mutex);
|
||||
idx = (hwdep->card->number * SNDRV_MINOR_HWDEPS) + hwdep->device;
|
||||
if (snd_hwdep_devices[idx] != hwdep) {
|
||||
if (snd_hwdep_search(hwdep->card, hwdep->device) != hwdep) {
|
||||
up(®ister_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -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);
|
||||
#endif
|
||||
snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device);
|
||||
snd_hwdep_devices[idx] = NULL;
|
||||
list_del(&hwdep->list);
|
||||
up(®ister_mutex);
|
||||
return snd_hwdep_free(hwdep);
|
||||
}
|
||||
|
@ -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,
|
||||
struct snd_info_buffer *buffer)
|
||||
{
|
||||
int idx;
|
||||
struct list_head *p;
|
||||
struct snd_hwdep *hwdep;
|
||||
|
||||
down(®ister_mutex);
|
||||
for (idx = 0; idx < SNDRV_CARDS * SNDRV_MINOR_HWDEPS; idx++) {
|
||||
hwdep = snd_hwdep_devices[idx];
|
||||
if (hwdep == NULL)
|
||||
continue;
|
||||
list_for_each(p, &snd_hwdep_devices) {
|
||||
hwdep = list_entry(p, struct snd_hwdep, list);
|
||||
snd_iprintf(buffer, "%02i-%02i: %s\n",
|
||||
idx / SNDRV_MINOR_HWDEPS,
|
||||
idx % SNDRV_MINOR_HWDEPS,
|
||||
hwdep->name);
|
||||
hwdep->card->number, hwdep->device, hwdep->name);
|
||||
}
|
||||
up(®ister_mutex);
|
||||
}
|
||||
|
@ -493,9 +487,8 @@ static int __init alsa_hwdep_init(void)
|
|||
{
|
||||
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) {
|
||||
entry->c.text.read_size = 512;
|
||||
entry->c.text.read_size = PAGE_SIZE;
|
||||
entry->c.text.read = snd_hwdep_proc_read;
|
||||
if (snd_info_register(entry) < 0) {
|
||||
snd_info_free_entry(entry);
|
||||
|
|
|
@ -41,12 +41,13 @@ MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_MIXER);
|
|||
|
||||
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_mixer_oss_file *fmixer;
|
||||
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;
|
||||
if (card->mixer_oss == NULL)
|
||||
return -ENODEV;
|
||||
|
@ -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);
|
||||
if ((err = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER,
|
||||
card, 0,
|
||||
&snd_mixer_oss_f_ops,
|
||||
&snd_mixer_oss_f_ops, card,
|
||||
name)) < 0) {
|
||||
snd_printk(KERN_ERR "unable to register OSS mixer device %i:%i\n",
|
||||
card->number, 0);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
int minor = iminor(inode);
|
||||
int cardnum = SNDRV_MINOR_OSS_CARD(minor);
|
||||
int device;
|
||||
int err;
|
||||
char task_name[32];
|
||||
struct snd_pcm *pcm;
|
||||
|
@ -1845,11 +1842,8 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
|
|||
int nonblock;
|
||||
wait_queue_t wait;
|
||||
|
||||
snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO);
|
||||
device = SNDRV_MINOR_OSS_DEVICE(minor) == SNDRV_MINOR_OSS_PCM1 ?
|
||||
adsp_map[cardnum] : dsp_map[cardnum];
|
||||
|
||||
pcm = snd_pcm_devices[(cardnum * SNDRV_PCM_DEVICES) + device];
|
||||
pcm = snd_lookup_oss_minor_data(iminor(inode),
|
||||
SNDRV_OSS_DEVICE_TYPE_PCM);
|
||||
if (pcm == NULL) {
|
||||
err = -ENODEV;
|
||||
goto __error1;
|
||||
|
@ -1890,7 +1884,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
|
|||
down(&pcm->open_mutex);
|
||||
while (1) {
|
||||
err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file,
|
||||
minor, psetup, csetup);
|
||||
iminor(inode), psetup, csetup);
|
||||
if (err >= 0)
|
||||
break;
|
||||
if (err == -EAGAIN) {
|
||||
|
@ -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);
|
||||
if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,
|
||||
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",
|
||||
pcm->card->number, pcm->device);
|
||||
}
|
||||
|
|
118
sound/core/pcm.c
118
sound/core/pcm.c
|
@ -33,7 +33,7 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Abramo Bagnara <abramo@alsa-proj
|
|||
MODULE_DESCRIPTION("Midlevel PCM code for ALSA.");
|
||||
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 DECLARE_MUTEX(register_mutex);
|
||||
|
||||
|
@ -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_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,
|
||||
struct snd_ctl_file *control,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
unsigned int tmp;
|
||||
|
||||
tmp = card->number * SNDRV_PCM_DEVICES;
|
||||
switch (cmd) {
|
||||
case SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE:
|
||||
{
|
||||
|
@ -57,14 +67,16 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
|
|||
|
||||
if (get_user(device, (int __user *)arg))
|
||||
return -EFAULT;
|
||||
down(®ister_mutex);
|
||||
device = device < 0 ? 0 : device + 1;
|
||||
while (device < SNDRV_PCM_DEVICES) {
|
||||
if (snd_pcm_devices[tmp + device])
|
||||
if (snd_pcm_search(card, device))
|
||||
break;
|
||||
device++;
|
||||
}
|
||||
if (device == SNDRV_PCM_DEVICES)
|
||||
device = -1;
|
||||
up(®ister_mutex);
|
||||
if (put_user(device, (int __user *)arg))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
@ -77,31 +89,44 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
|
|||
struct snd_pcm *pcm;
|
||||
struct snd_pcm_str *pstr;
|
||||
struct snd_pcm_substream *substream;
|
||||
int err;
|
||||
|
||||
info = (struct snd_pcm_info __user *)arg;
|
||||
if (get_user(device, &info->device))
|
||||
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))
|
||||
return -EFAULT;
|
||||
if (stream < 0 || stream > 1)
|
||||
return -EINVAL;
|
||||
pstr = &pcm->streams[stream];
|
||||
if (pstr->substream_count == 0)
|
||||
return -ENOENT;
|
||||
if (get_user(subdevice, &info->subdevice))
|
||||
return -EFAULT;
|
||||
if (subdevice >= pstr->substream_count)
|
||||
return -ENXIO;
|
||||
for (substream = pstr->substream; substream; substream = substream->next)
|
||||
down(®ister_mutex);
|
||||
pcm = snd_pcm_search(card, device);
|
||||
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)
|
||||
break;
|
||||
if (substream == NULL)
|
||||
return -ENXIO;
|
||||
return snd_pcm_info_user(substream, info);
|
||||
if (substream == NULL) {
|
||||
err = -ENXIO;
|
||||
goto _error;
|
||||
}
|
||||
err = snd_pcm_info_user(substream, info);
|
||||
_error:
|
||||
up(®ister_mutex);
|
||||
return err;
|
||||
}
|
||||
case SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE:
|
||||
{
|
||||
|
@ -865,8 +890,7 @@ void snd_pcm_release_substream(struct snd_pcm_substream *substream)
|
|||
|
||||
static int snd_pcm_dev_register(struct snd_device *device)
|
||||
{
|
||||
int idx, cidx, err;
|
||||
unsigned short minor;
|
||||
int cidx, err;
|
||||
struct snd_pcm_substream *substream;
|
||||
struct list_head *list;
|
||||
char str[16];
|
||||
|
@ -874,12 +898,11 @@ static int snd_pcm_dev_register(struct snd_device *device)
|
|||
|
||||
snd_assert(pcm != NULL && device != NULL, return -ENXIO);
|
||||
down(®ister_mutex);
|
||||
idx = (pcm->card->number * SNDRV_PCM_DEVICES) + pcm->device;
|
||||
if (snd_pcm_devices[idx]) {
|
||||
if (snd_pcm_search(pcm->card, pcm->device)) {
|
||||
up(®ister_mutex);
|
||||
return -EBUSY;
|
||||
}
|
||||
snd_pcm_devices[idx] = pcm;
|
||||
list_add_tail(&pcm->list, &snd_pcm_devices);
|
||||
for (cidx = 0; cidx < 2; cidx++) {
|
||||
int devtype = -1;
|
||||
if (pcm->streams[cidx].substream == NULL)
|
||||
|
@ -887,20 +910,19 @@ static int snd_pcm_dev_register(struct snd_device *device)
|
|||
switch (cidx) {
|
||||
case SNDRV_PCM_STREAM_PLAYBACK:
|
||||
sprintf(str, "pcmC%iD%ip", pcm->card->number, pcm->device);
|
||||
minor = SNDRV_MINOR_PCM_PLAYBACK + idx;
|
||||
devtype = SNDRV_DEVICE_TYPE_PCM_PLAYBACK;
|
||||
break;
|
||||
case SNDRV_PCM_STREAM_CAPTURE:
|
||||
sprintf(str, "pcmC%iD%ic", pcm->card->number, pcm->device);
|
||||
minor = SNDRV_MINOR_PCM_CAPTURE + idx;
|
||||
devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE;
|
||||
break;
|
||||
}
|
||||
if ((err = snd_register_device(devtype, pcm->card,
|
||||
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(®ister_mutex);
|
||||
return err;
|
||||
}
|
||||
|
@ -921,11 +943,10 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
|
|||
struct snd_pcm *pcm = device->device_data;
|
||||
struct list_head *list;
|
||||
struct snd_pcm_substream *substream;
|
||||
int idx, cidx;
|
||||
int cidx;
|
||||
|
||||
down(®ister_mutex);
|
||||
idx = (pcm->card->number * SNDRV_PCM_DEVICES) + pcm->device;
|
||||
snd_pcm_devices[idx] = NULL;
|
||||
list_del_init(&pcm->list);
|
||||
for (cidx = 0; cidx < 2; cidx++)
|
||||
for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
|
||||
if (substream->runtime)
|
||||
|
@ -941,15 +962,14 @@ static int snd_pcm_dev_disconnect(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 list_head *list;
|
||||
struct snd_pcm *pcm = device->device_data;
|
||||
|
||||
snd_assert(pcm != NULL, return -ENXIO);
|
||||
down(®ister_mutex);
|
||||
idx = (pcm->card->number * SNDRV_PCM_DEVICES) + pcm->device;
|
||||
snd_pcm_devices[idx] = NULL;
|
||||
list_del(&pcm->list);
|
||||
for (cidx = 0; cidx < 2; cidx++) {
|
||||
devtype = -1;
|
||||
switch (cidx) {
|
||||
|
@ -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 idx;
|
||||
struct list_head *p;
|
||||
|
||||
snd_assert(notify != NULL && notify->n_register != NULL && notify->n_unregister != NULL, return -EINVAL);
|
||||
down(®ister_mutex);
|
||||
if (nfree) {
|
||||
list_del(¬ify->list);
|
||||
for (idx = 0; idx < SNDRV_CARDS * SNDRV_PCM_DEVICES; idx++) {
|
||||
if (snd_pcm_devices[idx] == NULL)
|
||||
continue;
|
||||
notify->n_unregister(snd_pcm_devices[idx]);
|
||||
}
|
||||
list_for_each(p, &snd_pcm_devices)
|
||||
notify->n_unregister(list_entry(p,
|
||||
struct snd_pcm, list));
|
||||
} else {
|
||||
list_add_tail(¬ify->list, &snd_pcm_notify_list);
|
||||
for (idx = 0; idx < SNDRV_CARDS * SNDRV_PCM_DEVICES; idx++) {
|
||||
if (snd_pcm_devices[idx] == NULL)
|
||||
continue;
|
||||
notify->n_register(snd_pcm_devices[idx]);
|
||||
}
|
||||
list_for_each(p, &snd_pcm_devices)
|
||||
notify->n_register(list_entry(p, struct snd_pcm, list));
|
||||
}
|
||||
up(®ister_mutex);
|
||||
return 0;
|
||||
|
@ -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,
|
||||
struct snd_info_buffer *buffer)
|
||||
{
|
||||
int idx;
|
||||
struct list_head *p;
|
||||
struct snd_pcm *pcm;
|
||||
|
||||
down(®ister_mutex);
|
||||
for (idx = 0; idx < SNDRV_CARDS * SNDRV_PCM_DEVICES; idx++) {
|
||||
pcm = snd_pcm_devices[idx];
|
||||
if (pcm == NULL)
|
||||
continue;
|
||||
snd_iprintf(buffer, "%02i-%02i: %s : %s", idx / SNDRV_PCM_DEVICES,
|
||||
idx % SNDRV_PCM_DEVICES, pcm->id, pcm->name);
|
||||
list_for_each(p, &snd_pcm_devices) {
|
||||
pcm = list_entry(p, struct snd_pcm, list);
|
||||
snd_iprintf(buffer, "%02i-%02i: %s : %s",
|
||||
pcm->card->number, pcm->device, pcm->id, pcm->name);
|
||||
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
|
||||
snd_iprintf(buffer, " : playback %i",
|
||||
pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count);
|
||||
|
@ -1063,7 +1076,6 @@ static void __exit alsa_pcm_exit(void)
|
|||
module_init(alsa_pcm_init)
|
||||
module_exit(alsa_pcm_exit)
|
||||
|
||||
EXPORT_SYMBOL(snd_pcm_devices);
|
||||
EXPORT_SYMBOL(snd_pcm_new);
|
||||
EXPORT_SYMBOL(snd_pcm_new_stream);
|
||||
EXPORT_SYMBOL(snd_pcm_notify);
|
||||
|
|
|
@ -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);
|
||||
static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream,
|
||||
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)
|
|||
{
|
||||
struct file *file;
|
||||
struct inode *inode;
|
||||
unsigned short minor;
|
||||
unsigned int minor;
|
||||
|
||||
file = fget(fd);
|
||||
if (!file)
|
||||
return NULL;
|
||||
|
@ -1565,8 +1567,8 @@ static struct file *snd_pcm_file_fd(int fd)
|
|||
return NULL;
|
||||
}
|
||||
minor = iminor(inode);
|
||||
if (minor >= 256 ||
|
||||
minor % SNDRV_MINOR_DEVICES < SNDRV_MINOR_PCM_PLAYBACK) {
|
||||
if (!snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_PLAYBACK) &&
|
||||
!snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_CAPTURE)) {
|
||||
fput(file);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -2071,18 +2073,30 @@ static int snd_pcm_open_file(struct file *file,
|
|||
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)
|
||||
{
|
||||
int cardnum = SNDRV_MINOR_CARD(iminor(inode));
|
||||
int device = SNDRV_MINOR_DEVICE(iminor(inode));
|
||||
int err;
|
||||
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)
|
||||
{
|
||||
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;
|
||||
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) {
|
||||
err = -ENODEV;
|
||||
goto __error1;
|
||||
|
@ -2098,7 +2112,7 @@ static int snd_pcm_open(struct inode *inode, struct file *file)
|
|||
add_wait_queue(&pcm->open_wait, &wait);
|
||||
down(&pcm->open_mutex);
|
||||
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)
|
||||
break;
|
||||
if (err == -EAGAIN) {
|
||||
|
@ -3375,7 +3389,7 @@ struct file_operations snd_pcm_f_ops[2] = {
|
|||
.owner = THIS_MODULE,
|
||||
.write = snd_pcm_write,
|
||||
.writev = snd_pcm_writev,
|
||||
.open = snd_pcm_open,
|
||||
.open = snd_pcm_playback_open,
|
||||
.release = snd_pcm_release,
|
||||
.poll = snd_pcm_playback_poll,
|
||||
.unlocked_ioctl = snd_pcm_playback_ioctl,
|
||||
|
@ -3387,7 +3401,7 @@ struct file_operations snd_pcm_f_ops[2] = {
|
|||
.owner = THIS_MODULE,
|
||||
.read = snd_pcm_read,
|
||||
.readv = snd_pcm_readv,
|
||||
.open = snd_pcm_open,
|
||||
.open = snd_pcm_capture_open,
|
||||
.release = snd_pcm_release,
|
||||
.poll = snd_pcm_capture_poll,
|
||||
.unlocked_ioctl = snd_pcm_capture_ioctl,
|
||||
|
|
|
@ -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_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 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)
|
||||
{
|
||||
switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) {
|
||||
|
@ -214,7 +226,7 @@ int snd_rawmidi_drain_input(struct snd_rawmidi_substream *substream)
|
|||
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)
|
||||
{
|
||||
struct snd_rawmidi *rmidi;
|
||||
|
@ -225,7 +237,9 @@ int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice,
|
|||
|
||||
if (rfile)
|
||||
rfile->input = rfile->output = NULL;
|
||||
rmidi = snd_rawmidi_devices[(cardnum * SNDRV_RAWMIDI_DEVICES) + device];
|
||||
down(®ister_mutex);
|
||||
rmidi = snd_rawmidi_search(card, device);
|
||||
up(®ister_mutex);
|
||||
if (rmidi == NULL) {
|
||||
err = -ENODEV;
|
||||
goto __error1;
|
||||
|
@ -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)
|
||||
{
|
||||
int maj = imajor(inode);
|
||||
int cardnum;
|
||||
struct snd_card *card;
|
||||
int device, subdevice;
|
||||
int subdevice;
|
||||
unsigned short fflags;
|
||||
int err;
|
||||
struct snd_rawmidi *rmidi;
|
||||
|
@ -380,27 +393,18 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
|
|||
struct snd_ctl_file *kctl;
|
||||
|
||||
if (maj == snd_major) {
|
||||
cardnum = SNDRV_MINOR_CARD(iminor(inode));
|
||||
cardnum %= SNDRV_CARDS;
|
||||
device = SNDRV_MINOR_DEVICE(iminor(inode)) - SNDRV_MINOR_RAWMIDI;
|
||||
device %= SNDRV_MINOR_RAWMIDIS;
|
||||
rmidi = snd_lookup_minor_data(iminor(inode),
|
||||
SNDRV_DEVICE_TYPE_RAWMIDI);
|
||||
#ifdef CONFIG_SND_OSSEMUL
|
||||
} else if (maj == SOUND_MAJOR) {
|
||||
cardnum = SNDRV_MINOR_OSS_CARD(iminor(inode));
|
||||
cardnum %= SNDRV_CARDS;
|
||||
device = SNDRV_MINOR_OSS_DEVICE(iminor(inode)) == SNDRV_MINOR_OSS_MIDI ?
|
||||
midi_map[cardnum] : amidi_map[cardnum];
|
||||
rmidi = snd_lookup_oss_minor_data(iminor(inode),
|
||||
SNDRV_OSS_DEVICE_TYPE_MIDI);
|
||||
#endif
|
||||
} else
|
||||
return -ENXIO;
|
||||
|
||||
rmidi = snd_rawmidi_devices[(cardnum * SNDRV_RAWMIDI_DEVICES) + device];
|
||||
if (rmidi == NULL)
|
||||
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))
|
||||
return -EINVAL; /* invalid combination */
|
||||
card = rmidi->card;
|
||||
|
@ -430,7 +434,8 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
|
|||
}
|
||||
}
|
||||
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)
|
||||
break;
|
||||
if (err == -EAGAIN) {
|
||||
|
@ -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_substream *substream;
|
||||
struct list_head *list;
|
||||
if (info->device >= SNDRV_RAWMIDI_DEVICES)
|
||||
return -ENXIO;
|
||||
rmidi = snd_rawmidi_devices[card->number * SNDRV_RAWMIDI_DEVICES + info->device];
|
||||
|
||||
down(®ister_mutex);
|
||||
rmidi = snd_rawmidi_search(card, info->device);
|
||||
up(®ister_mutex);
|
||||
if (!rmidi)
|
||||
return -ENXIO;
|
||||
if (info->stream < 0 || info->stream > 1)
|
||||
|
@ -803,9 +809,7 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card,
|
|||
unsigned long arg)
|
||||
{
|
||||
void __user *argp = (void __user *)arg;
|
||||
unsigned int tmp;
|
||||
|
||||
tmp = card->number * SNDRV_RAWMIDI_DEVICES;
|
||||
switch (cmd) {
|
||||
case SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE:
|
||||
{
|
||||
|
@ -813,14 +817,16 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card,
|
|||
|
||||
if (get_user(device, (int __user *)argp))
|
||||
return -EFAULT;
|
||||
down(®ister_mutex);
|
||||
device = device < 0 ? 0 : device + 1;
|
||||
while (device < SNDRV_RAWMIDI_DEVICES) {
|
||||
if (snd_rawmidi_devices[tmp + device])
|
||||
if (snd_rawmidi_search(card, device))
|
||||
break;
|
||||
device++;
|
||||
}
|
||||
if (device == SNDRV_RAWMIDI_DEVICES)
|
||||
device = -1;
|
||||
up(®ister_mutex);
|
||||
if (put_user(device, (int __user *)argp))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
@ -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)
|
||||
{
|
||||
int idx, err;
|
||||
int err;
|
||||
struct snd_info_entry *entry;
|
||||
char name[16];
|
||||
struct snd_rawmidi *rmidi = device->device_data;
|
||||
|
@ -1501,25 +1507,24 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
|
|||
if (rmidi->device >= SNDRV_RAWMIDI_DEVICES)
|
||||
return -ENOMEM;
|
||||
down(®ister_mutex);
|
||||
idx = (rmidi->card->number * SNDRV_RAWMIDI_DEVICES) + rmidi->device;
|
||||
if (snd_rawmidi_devices[idx] != NULL) {
|
||||
if (snd_rawmidi_search(rmidi->card, rmidi->device)) {
|
||||
up(®ister_mutex);
|
||||
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);
|
||||
if ((err = snd_register_device(SNDRV_DEVICE_TYPE_RAWMIDI,
|
||||
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_rawmidi_devices[idx] = NULL;
|
||||
list_del(&rmidi->list);
|
||||
up(®ister_mutex);
|
||||
return err;
|
||||
}
|
||||
if (rmidi->ops && rmidi->ops->dev_register &&
|
||||
(err = rmidi->ops->dev_register(rmidi)) < 0) {
|
||||
snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device);
|
||||
snd_rawmidi_devices[idx] = NULL;
|
||||
list_del(&rmidi->list);
|
||||
up(®ister_mutex);
|
||||
return err;
|
||||
}
|
||||
|
@ -1527,8 +1532,8 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
|
|||
rmidi->ossreg = 0;
|
||||
if ((int)rmidi->device == midi_map[rmidi->card->number]) {
|
||||
if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI,
|
||||
rmidi->card, 0,
|
||||
&snd_rawmidi_f_ops, name) < 0) {
|
||||
rmidi->card, 0, &snd_rawmidi_f_ops,
|
||||
rmidi, name) < 0) {
|
||||
snd_printk(KERN_ERR "unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 0);
|
||||
} else {
|
||||
rmidi->ossreg++;
|
||||
|
@ -1539,8 +1544,8 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
|
|||
}
|
||||
if ((int)rmidi->device == amidi_map[rmidi->card->number]) {
|
||||
if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI,
|
||||
rmidi->card, 1,
|
||||
&snd_rawmidi_f_ops, name) < 0) {
|
||||
rmidi->card, 1, &snd_rawmidi_f_ops,
|
||||
rmidi, name) < 0) {
|
||||
snd_printk(KERN_ERR "unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 1);
|
||||
} else {
|
||||
rmidi->ossreg++;
|
||||
|
@ -1576,24 +1581,20 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
|
|||
static int snd_rawmidi_dev_disconnect(struct snd_device *device)
|
||||
{
|
||||
struct snd_rawmidi *rmidi = device->device_data;
|
||||
int idx;
|
||||
|
||||
down(®ister_mutex);
|
||||
idx = (rmidi->card->number * SNDRV_RAWMIDI_DEVICES) + rmidi->device;
|
||||
snd_rawmidi_devices[idx] = NULL;
|
||||
list_del_init(&rmidi->list);
|
||||
up(®ister_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_rawmidi_dev_unregister(struct snd_device *device)
|
||||
{
|
||||
int idx;
|
||||
struct snd_rawmidi *rmidi = device->device_data;
|
||||
|
||||
snd_assert(rmidi != NULL, return -ENXIO);
|
||||
down(®ister_mutex);
|
||||
idx = (rmidi->card->number * SNDRV_RAWMIDI_DEVICES) + rmidi->device;
|
||||
snd_rawmidi_devices[idx] = NULL;
|
||||
list_del(&rmidi->list);
|
||||
if (rmidi->proc_entry) {
|
||||
snd_info_unregister(rmidi->proc_entry);
|
||||
rmidi->proc_entry = NULL;
|
||||
|
|
|
@ -225,7 +225,7 @@ register_device(void)
|
|||
down(®ister_mutex);
|
||||
if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER,
|
||||
NULL, 0,
|
||||
&seq_oss_f_ops,
|
||||
&seq_oss_f_ops, NULL,
|
||||
SNDRV_SEQ_OSS_DEVNAME)) < 0) {
|
||||
snd_printk(KERN_ERR "can't register device seq\n");
|
||||
up(®ister_mutex);
|
||||
|
@ -233,7 +233,7 @@ register_device(void)
|
|||
}
|
||||
if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC,
|
||||
NULL, 0,
|
||||
&seq_oss_f_ops,
|
||||
&seq_oss_f_ops, NULL,
|
||||
SNDRV_SEQ_OSS_DEVNAME)) < 0) {
|
||||
snd_printk(KERN_ERR "can't register device music\n");
|
||||
snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0);
|
||||
|
|
|
@ -2531,7 +2531,7 @@ int __init snd_sequencer_device_init(void)
|
|||
return -ERESTARTSYS;
|
||||
|
||||
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(®ister_mutex);
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -183,7 +183,10 @@ static int midisynth_subscribe(void *private_data, struct snd_seq_port_subscribe
|
|||
struct snd_rawmidi_params params;
|
||||
|
||||
/* 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");
|
||||
return err;
|
||||
}
|
||||
|
@ -221,7 +224,10 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info
|
|||
struct snd_rawmidi_params params;
|
||||
|
||||
/* 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");
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -60,7 +60,6 @@ MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR);
|
|||
int snd_ecards_limit;
|
||||
|
||||
static struct snd_minor *snd_minors[SNDRV_OS_MINORS];
|
||||
|
||||
static DECLARE_MUTEX(sound_mutex);
|
||||
|
||||
extern struct class *sound_class;
|
||||
|
@ -107,6 +106,31 @@ static void snd_request_other(int minor)
|
|||
|
||||
#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)
|
||||
{
|
||||
int minor = iminor(inode);
|
||||
|
@ -183,6 +207,7 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev)
|
|||
* @card: the card instance
|
||||
* @dev: the device index
|
||||
* @f_ops: the file operations
|
||||
* @private_data: user pointer for f_ops->open()
|
||||
* @name: the device file name
|
||||
*
|
||||
* 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)
|
|||
* Retrurns zero if successful, or a negative error code on failure.
|
||||
*/
|
||||
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);
|
||||
struct snd_minor *preg;
|
||||
|
@ -207,6 +233,7 @@ int snd_register_device(int type, struct snd_card *card, int dev,
|
|||
preg->card = card ? card->number : -1;
|
||||
preg->device = dev;
|
||||
preg->f_ops = f_ops;
|
||||
preg->private_data = private_data;
|
||||
strcpy(preg->name, name);
|
||||
down(&sound_mutex);
|
||||
if (snd_minors[minor]) {
|
||||
|
@ -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 minor = snd_kernel_minor(type, card, dev);
|
||||
int cardnum, minor;
|
||||
struct snd_minor *mptr;
|
||||
|
||||
if (minor < 0)
|
||||
return minor;
|
||||
cardnum = card ? card->number : -1;
|
||||
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);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -392,9 +424,11 @@ EXPORT_SYMBOL(snd_request_card);
|
|||
#endif
|
||||
EXPORT_SYMBOL(snd_register_device);
|
||||
EXPORT_SYMBOL(snd_unregister_device);
|
||||
EXPORT_SYMBOL(snd_lookup_minor_data);
|
||||
#if defined(CONFIG_SND_OSSEMUL)
|
||||
EXPORT_SYMBOL(snd_register_oss_device);
|
||||
EXPORT_SYMBOL(snd_unregister_oss_device);
|
||||
EXPORT_SYMBOL(snd_lookup_oss_minor_data);
|
||||
#endif
|
||||
/* memory.c */
|
||||
EXPORT_SYMBOL(copy_to_user_fromio);
|
||||
|
|
|
@ -38,9 +38,25 @@
|
|||
#define SNDRV_OSS_MINORS 128
|
||||
|
||||
static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS];
|
||||
|
||||
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)
|
||||
{
|
||||
int minor;
|
||||
|
@ -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,
|
||||
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_unit;
|
||||
|
@ -97,6 +114,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,
|
|||
preg->card = card ? card->number : -1;
|
||||
preg->device = dev;
|
||||
preg->f_ops = f_ops;
|
||||
preg->private_data = private_data;
|
||||
down(&sound_oss_mutex);
|
||||
snd_oss_minors[minor] = preg;
|
||||
minor_unit = SNDRV_MINOR_OSS_DEVICE(minor);
|
||||
|
@ -121,6 +139,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,
|
|||
carddev);
|
||||
if (register2 != track2)
|
||||
goto __end;
|
||||
snd_oss_minors[track2] = preg;
|
||||
}
|
||||
up(&sound_oss_mutex);
|
||||
return 0;
|
||||
|
@ -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);
|
||||
break;
|
||||
}
|
||||
if (track2 >= 0)
|
||||
if (track2 >= 0) {
|
||||
unregister_sound_special(track2);
|
||||
snd_oss_minors[track2] = NULL;
|
||||
}
|
||||
snd_oss_minors[minor] = NULL;
|
||||
up(&sound_oss_mutex);
|
||||
kfree(mptr);
|
||||
|
|
|
@ -1952,8 +1952,8 @@ static int __init alsa_timer_init(void)
|
|||
if ((err = snd_timer_register_system()) < 0)
|
||||
snd_printk(KERN_ERR "unable to register system timer (%i)\n",
|
||||
err);
|
||||
if ((err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER,
|
||||
NULL, 0, &snd_timer_f_ops, "timer")) < 0)
|
||||
if ((err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER, NULL, 0,
|
||||
&snd_timer_f_ops, NULL, "timer")) < 0)
|
||||
snd_printk(KERN_ERR "unable to register timer device (%i)\n",
|
||||
err);
|
||||
return 0;
|
||||
|
|
Loading…
Reference in a new issue