Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 05662205 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

ALSA: seq: Define driver object in each driver



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: default avatarTakashi Iwai <tiwai@suse.de>
parent af03c243
Loading
Loading
Loading
Loading
+19 −8
Original line number Diff line number Diff line
@@ -41,8 +41,10 @@ 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
@@ -50,15 +52,19 @@ struct snd_seq_device {
 *		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
 */
@@ -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
+13 −7
Original line number Diff line number Diff line
@@ -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)
@@ -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();
@@ -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();
+4 −2
Original line number Diff line number Diff line
@@ -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);
@@ -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;
+2 −2
Original line number Diff line number Diff line
@@ -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);
+10 −83
Original line number Diff line number Diff line
@@ -52,16 +52,6 @@ MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
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
 */
@@ -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
Loading