Skip to content

Commit

Permalink
[ALSA] dynamic minors (3/6): store device-specific object pointers dy…
Browse files Browse the repository at this point in the history
…namically

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>
  • Loading branch information
Clemens Ladisch authored and Jaroslav Kysela committed Jan 3, 2006
1 parent 6983b72 commit f87135f
Show file tree
Hide file tree
Showing 17 changed files with 278 additions and 197 deletions.
9 changes: 7 additions & 2 deletions include/sound/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) */
};
Expand All @@ -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);
Expand Down
1 change: 1 addition & 0 deletions include/sound/hwdep.h
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down
2 changes: 1 addition & 1 deletion include/sound/pcm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
6 changes: 3 additions & 3 deletions include/sound/rawmidi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -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);
Expand Down
7 changes: 3 additions & 4 deletions sound/core/control.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down
91 changes: 42 additions & 49 deletions sound/core/hwdep.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,27 @@ 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);
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)
{
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -265,42 +265,43 @@ 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:
{
int device;

if (get_user(device, (int __user *)arg))
return -EFAULT;
down(&register_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(&register_mutex);
if (put_user(device, (int __user *)arg))
return -EFAULT;
return 0;
}
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(&register_mutex);
hwdep = snd_hwdep_search(card, device);
if (hwdep)
err = snd_hwdep_info(hwdep, info);
else
err = -ENXIO;
up(&register_mutex);
return err;
}
}
return -ENOIOCTLCMD;
Expand Down Expand Up @@ -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(&register_mutex);
idx = (hwdep->card->number * SNDRV_MINOR_HWDEPS) + hwdep->device;
if (snd_hwdep_devices[idx]) {
if (snd_hwdep_search(hwdep->card, hwdep->device)) {
up(&register_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(&register_mutex);
return err;
}
Expand All @@ -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);
Expand All @@ -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(&register_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(&register_mutex);
return -EINVAL;
}
Expand All @@ -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(&register_mutex);
return snd_hwdep_free(hwdep);
}
Expand All @@ -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(&register_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(&register_mutex);
}
Expand All @@ -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);
Expand Down
7 changes: 4 additions & 3 deletions sound/core/oss/mixer_oss.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
14 changes: 4 additions & 10 deletions sound/core/oss/pcm_oss.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}
Expand Down
Loading

0 comments on commit f87135f

Please sign in to comment.