Skip to content

Commit

Permalink
ALSA: seq: Define driver object in each driver
Browse files Browse the repository at this point in the history
This patch moves the driver object initialization and allocation to
each driver's module init/exit code like other normal drivers.  The
snd_seq_driver struct is now published in seq_device.h, and each
driver is responsible to define it with proper driver attributes
(name, probe and remove) with snd_seq_driver specific attributes as id
and argsize fields.  The helper functions snd_seq_driver_register(),
snd_seq_driver_unregister() and module_snd_seq_driver() are used for
simplifying codes.

Signed-off-by: Takashi Iwai <[email protected]>
  • Loading branch information
tiwai committed Feb 12, 2015
1 parent af03c24 commit 0566220
Show file tree
Hide file tree
Showing 10 changed files with 124 additions and 191 deletions.
27 changes: 19 additions & 8 deletions include/sound/seq_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,24 +41,30 @@ struct snd_seq_device {
#define to_seq_dev(_dev) \
container_of(_dev, struct snd_seq_device, dev)

/* sequencer driver */

/* driver operators
* init_device:
* probe:
* Initialize the device with given parameters.
* Typically,
* 1. call snd_hwdep_new
* 2. allocate private data and initialize it
* 3. call snd_hwdep_register
* 4. store the instance to dev->driver_data pointer.
*
* free_device:
* remove:
* Release the private data.
* Typically, call snd_device_free(dev->card, dev->driver_data)
*/
struct snd_seq_dev_ops {
int (*init_device)(struct snd_seq_device *dev);
int (*free_device)(struct snd_seq_device *dev);
struct snd_seq_driver {
struct device_driver driver;
char *id;
int argsize;
};

#define to_seq_drv(_drv) \
container_of(_drv, struct snd_seq_driver, driver)

/*
* prototypes
*/
Expand All @@ -69,12 +75,17 @@ void snd_seq_device_load_drivers(void);
#endif
int snd_seq_device_new(struct snd_card *card, int device, const char *id,
int argsize, struct snd_seq_device **result);
int snd_seq_device_register_driver(const char *id,
struct snd_seq_dev_ops *entry, int argsize);
int snd_seq_device_unregister_driver(const char *id);

#define SNDRV_SEQ_DEVICE_ARGPTR(dev) (void *)((char *)(dev) + sizeof(struct snd_seq_device))

int __must_check __snd_seq_driver_register(struct snd_seq_driver *drv,
struct module *mod);
#define snd_seq_driver_register(drv) \
__snd_seq_driver_register(drv, THIS_MODULE)
void snd_seq_driver_unregister(struct snd_seq_driver *drv);

#define module_snd_seq_driver(drv) \
module_driver(drv, snd_seq_driver_register, snd_seq_driver_unregister)

/*
* id strings for generic devices
Expand Down
20 changes: 13 additions & 7 deletions sound/core/seq/oss/seq_oss.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,19 @@ static unsigned int odev_poll(struct file *file, poll_table * wait);
* module interface
*/

static struct snd_seq_driver seq_oss_synth_driver = {
.driver = {
.name = KBUILD_MODNAME,
.probe = snd_seq_oss_synth_probe,
.remove = snd_seq_oss_synth_remove,
},
.id = SNDRV_SEQ_DEV_ID_OSS,
.argsize = sizeof(struct snd_seq_oss_reg),
};

static int __init alsa_seq_oss_init(void)
{
int rc;
static struct snd_seq_dev_ops ops = {
snd_seq_oss_synth_register,
snd_seq_oss_synth_unregister,
};

snd_seq_autoload_lock();
if ((rc = register_device()) < 0)
Expand All @@ -86,8 +92,8 @@ static int __init alsa_seq_oss_init(void)
goto error;
}

if ((rc = snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_OSS, &ops,
sizeof(struct snd_seq_oss_reg))) < 0) {
rc = snd_seq_driver_register(&seq_oss_synth_driver);
if (rc < 0) {
snd_seq_oss_delete_client();
unregister_proc();
unregister_device();
Expand All @@ -104,7 +110,7 @@ static int __init alsa_seq_oss_init(void)

static void __exit alsa_seq_oss_exit(void)
{
snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_OSS);
snd_seq_driver_unregister(&seq_oss_synth_driver);
snd_seq_oss_delete_client();
unregister_proc();
unregister_device();
Expand Down
6 changes: 4 additions & 2 deletions sound/core/seq/oss/seq_oss_synth.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,9 @@ snd_seq_oss_synth_init(void)
* registration of the synth device
*/
int
snd_seq_oss_synth_register(struct snd_seq_device *dev)
snd_seq_oss_synth_probe(struct device *_dev)
{
struct snd_seq_device *dev = to_seq_dev(_dev);
int i;
struct seq_oss_synth *rec;
struct snd_seq_oss_reg *reg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
Expand Down Expand Up @@ -149,8 +150,9 @@ snd_seq_oss_synth_register(struct snd_seq_device *dev)


int
snd_seq_oss_synth_unregister(struct snd_seq_device *dev)
snd_seq_oss_synth_remove(struct device *_dev)
{
struct snd_seq_device *dev = to_seq_dev(_dev);
int index;
struct seq_oss_synth *rec = dev->driver_data;
unsigned long flags;
Expand Down
4 changes: 2 additions & 2 deletions sound/core/seq/oss/seq_oss_synth.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
#include <sound/seq_device.h>

void snd_seq_oss_synth_init(void);
int snd_seq_oss_synth_register(struct snd_seq_device *dev);
int snd_seq_oss_synth_unregister(struct snd_seq_device *dev);
int snd_seq_oss_synth_probe(struct device *dev);
int snd_seq_oss_synth_remove(struct device *dev);
void snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp);
void snd_seq_oss_synth_setup_midi(struct seq_oss_devinfo *dp);
void snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp);
Expand Down
93 changes: 10 additions & 83 deletions sound/core/seq/seq_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,6 @@ MODULE_AUTHOR("Takashi Iwai <[email protected]>");
MODULE_DESCRIPTION("ALSA sequencer device management");
MODULE_LICENSE("GPL");

struct snd_seq_driver {
struct device_driver driver;
const char *id;
int argsize;
struct snd_seq_dev_ops ops;
};

#define to_seq_drv(_drv) \
container_of(_drv, struct snd_seq_driver, driver)

/*
* bus definition
*/
Expand Down Expand Up @@ -263,86 +253,23 @@ int snd_seq_device_new(struct snd_card *card, int device, const char *id,
EXPORT_SYMBOL(snd_seq_device_new);

/*
* driver binding - just pass to each driver callback
* driver registration
*/
static int snd_seq_drv_probe(struct device *dev)
int __snd_seq_driver_register(struct snd_seq_driver *drv, struct module *mod)
{
struct snd_seq_driver *sdrv = to_seq_drv(dev->driver);
struct snd_seq_device *sdev = to_seq_dev(dev);

return sdrv->ops.init_device(sdev);
}

static int snd_seq_drv_remove(struct device *dev)
{
struct snd_seq_driver *sdrv = to_seq_drv(dev->driver);
struct snd_seq_device *sdev = to_seq_dev(dev);

return sdrv->ops.free_device(sdev);
}

/*
* register device driver
* id = driver id
* entry = driver operators - duplicated to each instance
*/
int snd_seq_device_register_driver(const char *id,
struct snd_seq_dev_ops *entry, int argsize)
{
struct snd_seq_driver *sdrv;
int err;

if (id == NULL || entry == NULL ||
entry->init_device == NULL || entry->free_device == NULL)
if (WARN_ON(!drv->driver.name || !drv->id))
return -EINVAL;

sdrv = kzalloc(sizeof(*sdrv), GFP_KERNEL);
if (!sdrv)
return -ENOMEM;

sdrv->driver.name = id;
sdrv->driver.bus = &snd_seq_bus_type;
sdrv->driver.probe = snd_seq_drv_probe;
sdrv->driver.remove = snd_seq_drv_remove;
sdrv->id = id;
sdrv->argsize = argsize;
sdrv->ops = *entry;

err = driver_register(&sdrv->driver);
if (err < 0)
kfree(sdrv);
return err;
}
EXPORT_SYMBOL(snd_seq_device_register_driver);

/* callback to find a specific driver; data is a pointer to the id string ptr.
* when the id matches, store the driver pointer in return and break the loop.
*/
static int find_drv(struct device_driver *drv, void *data)
{
struct snd_seq_driver *sdrv = to_seq_drv(drv);
void **ptr = (void **)data;

if (strcmp(sdrv->id, *ptr))
return 0; /* id don't match, continue the loop */
*ptr = sdrv;
return 1; /* break the loop */
drv->driver.bus = &snd_seq_bus_type;
drv->driver.owner = mod;
return driver_register(&drv->driver);
}
EXPORT_SYMBOL_GPL(__snd_seq_driver_register);

/*
* unregister the specified driver
*/
int snd_seq_device_unregister_driver(const char *id)
void snd_seq_driver_unregister(struct snd_seq_driver *drv)
{
struct snd_seq_driver *sdrv = (struct snd_seq_driver *)id;

if (!bus_for_each_drv(&snd_seq_bus_type, NULL, &sdrv, find_drv))
return -ENXIO;
driver_unregister(&sdrv->driver);
kfree(sdrv);
return 0;
driver_unregister(&drv->driver);
}
EXPORT_SYMBOL(snd_seq_device_unregister_driver);
EXPORT_SYMBOL_GPL(snd_seq_driver_unregister);

/*
* module part
Expand Down
28 changes: 18 additions & 10 deletions sound/core/seq/seq_midi.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,8 +273,9 @@ static void snd_seq_midisynth_delete(struct seq_midisynth *msynth)

/* register new midi synth port */
static int
snd_seq_midisynth_register_port(struct snd_seq_device *dev)
snd_seq_midisynth_probe(struct device *_dev)
{
struct snd_seq_device *dev = to_seq_dev(_dev);
struct seq_midisynth_client *client;
struct seq_midisynth *msynth, *ms;
struct snd_seq_port_info *port;
Expand Down Expand Up @@ -427,8 +428,9 @@ snd_seq_midisynth_register_port(struct snd_seq_device *dev)

/* release midi synth port */
static int
snd_seq_midisynth_unregister_port(struct snd_seq_device *dev)
snd_seq_midisynth_remove(struct device *_dev)
{
struct snd_seq_device *dev = to_seq_dev(_dev);
struct seq_midisynth_client *client;
struct seq_midisynth *msynth;
struct snd_card *card = dev->card;
Expand Down Expand Up @@ -457,23 +459,29 @@ snd_seq_midisynth_unregister_port(struct snd_seq_device *dev)
return 0;
}

static struct snd_seq_driver seq_midisynth_driver = {
.driver = {
.name = KBUILD_MODNAME,
.probe = snd_seq_midisynth_probe,
.remove = snd_seq_midisynth_remove,
},
.id = SNDRV_SEQ_DEV_ID_MIDISYNTH,
.argsize = 0,
};

static int __init alsa_seq_midi_init(void)
{
static struct snd_seq_dev_ops ops = {
snd_seq_midisynth_register_port,
snd_seq_midisynth_unregister_port,
};
memset(&synths, 0, sizeof(synths));
int err;

snd_seq_autoload_lock();
snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_MIDISYNTH, &ops, 0);
err = snd_seq_driver_register(&seq_midisynth_driver);
snd_seq_autoload_unlock();
return 0;
return err;
}

static void __exit alsa_seq_midi_exit(void)
{
snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_MIDISYNTH);
snd_seq_driver_unregister(&seq_midisynth_driver);
}

module_init(alsa_seq_midi_init)
Expand Down
34 changes: 14 additions & 20 deletions sound/drivers/opl3/opl3_seq.c
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,9 @@ static int snd_opl3_synth_create_port(struct snd_opl3 * opl3)

/* ------------------------------ */

static int snd_opl3_seq_new_device(struct snd_seq_device *dev)
static int snd_opl3_seq_probe(struct device *_dev)
{
struct snd_seq_device *dev = to_seq_dev(_dev);
struct snd_opl3 *opl3;
int client, err;
char name[32];
Expand Down Expand Up @@ -257,8 +258,9 @@ static int snd_opl3_seq_new_device(struct snd_seq_device *dev)
return 0;
}

static int snd_opl3_seq_delete_device(struct snd_seq_device *dev)
static int snd_opl3_seq_remove(struct device *_dev)
{
struct snd_seq_device *dev = to_seq_dev(_dev);
struct snd_opl3 *opl3;

opl3 = *(struct snd_opl3 **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
Expand All @@ -275,22 +277,14 @@ static int snd_opl3_seq_delete_device(struct snd_seq_device *dev)
return 0;
}

static int __init alsa_opl3_seq_init(void)
{
static struct snd_seq_dev_ops ops =
{
snd_opl3_seq_new_device,
snd_opl3_seq_delete_device
};

return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_OPL3, &ops,
sizeof(struct snd_opl3 *));
}

static void __exit alsa_opl3_seq_exit(void)
{
snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_OPL3);
}
static struct snd_seq_driver opl3_seq_driver = {
.driver = {
.name = KBUILD_MODNAME,
.probe = snd_opl3_seq_probe,
.remove = snd_opl3_seq_remove,
},
.id = SNDRV_SEQ_DEV_ID_OPL3,
.argsize = sizeof(struct snd_opl3 *),
};

module_init(alsa_opl3_seq_init)
module_exit(alsa_opl3_seq_exit)
module_snd_seq_driver(opl3_seq_driver);
Loading

0 comments on commit 0566220

Please sign in to comment.