[alsa-devel] [PATCH 5/6] compress: add the core file

Takashi Iwai tiwai at suse.de
Wed Nov 23 18:03:04 CET 2011


At Tue, 22 Nov 2011 14:21:59 +0530,
Vinod Koul wrote:
> 
> This patch adds core.c, the file which implements the ioctls and
> registers the devices
> 
> Signed-off-by: Vinod Koul <vinod.koul at linux.intel.com>
> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart at linux.intel.com>

A general note: it's not necessarily to split playback and capture
devices.  For example, rawmidi has a single device for full-duplex.
In the case of PCM, we had to split them because of mmap.  The mmap
for the capture was supposed not to be read-only, some apps may want
to add mark on the buffer.  But, if this isn't the case for
compression devices, you can have a single device serving for both
playback and capture.  The direction can be checked by the open flag.

> +#define FORMAT(fmt) "%s: %d: " fmt, __func__, __LINE__
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " FORMAT(fmt)

Is this referred anywhere?

> +#include <sound/snd_compress_params.h>
> +#include <sound/compress_offload.h>
> +#include <sound/compress_driver.h>
> +#include <sound/core.h>
> +#include <sound/initval.h>

In general, sound/core.h is included at first.


> +static DEFINE_MUTEX(device_mutex);
> +
> +struct snd_compr_file {
> +	unsigned long caps;
> +	struct snd_compr_stream stream;
> +};
> +
> +static int snd_compr_open(struct file *f,  struct snd_compr *compr, int type)
> +{
> +	struct snd_compr_file *data;
> +	struct snd_compr_runtime *runtime;
> +	int ret;
> +
> +	mutex_lock(&device_mutex);

Do you need a global lock for opening a device, too?  Just to be sure,
since I see no obvious need.  (Anyway you don't need to have a lock at
this early place before a bunch of kmallocs.  The lock should be done
as small as possible.)

> +static int snd_compr_free(struct inode *inode, struct file *f)
> +{
> +	struct snd_compr_file *data = f->private_data;
> +	mutex_lock(&device_mutex);
> +	data->stream.ops->free(&data->stream);
> +	kfree(data->stream.runtime->buffer);
> +	kfree(data->stream.runtime);
> +	kfree(data);
> +	mutex_unlock(&device_mutex);

Ditto.  Do you need a global lock?

> +static int
> +snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg)
> +{
> +	struct snd_compr_avail ioctl_avail;
> +
> +	snd_compr_calc_avail(stream, &ioctl_avail);
> +	if (copy_to_user((unsigned long __user *)arg,
> +				&ioctl_avail, sizeof(ioctl_avail)))

snd_compr_calc_avail() doesn't initialize the pointer, so this may
leak some kernel space.

> +
> +unsigned int snd_compr_pb_poll(struct file *f, poll_table *wait)

Missing static?

> +
> +unsigned int snd_compr_cap_poll(struct file *f, poll_table *wait)

Ditto.


> +void snd_compr_fragment_elapsed(struct snd_compr_stream *stream)
> +{
> +	pr_debug("fragment elapsed called\n");
> +	if (stream->direction !=  SNDRV_DEVICE_TYPE_COMPR_PLAYBACK)
> +		return;
> +	wake_up(&stream->runtime->sleep);
> +}
> +EXPORT_SYMBOL_GPL(snd_compr_fragment_elapsed);
> +
> +void snd_compr_frame_elapsed(struct snd_compr_stream *stream)
> +{
> +	if (stream->direction != SNDRV_DEVICE_TYPE_COMPR_CAPTURE)
> +		return;
> +	wake_up(&stream->runtime->sleep);
> +}
> +EXPORT_SYMBOL_GPL(snd_compr_frame_elapsed);

These are better to be inlined...
(And fragment and frame for different directions?  Hm, not so
intuitive :)

> +static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
> +{
> +	struct snd_compr_file *data = f->private_data;
> +	struct snd_compr_stream *stream;
> +	int retval = -ENOTTY;
> +
> +	BUG_ON(!data);
> +	stream = &data->stream;
> +	BUG_ON(!stream);

Avoid BUG_ON() unless you really want to stop the whole operation at
this option (such as memory corruption).


> +	mutex_lock(&stream->device->lock);
> +	switch (_IOC_NR(cmd)) {
> +	case _IOC_NR(SNDRV_COMPRESS_IOCTL_VERSION):
> +		put_user(SNDRV_COMPRESS_VERSION,
> +				(int __user *)arg) ? -EFAULT : 0;
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_GET_CAPS):
> +		retval = snd_compr_get_caps(stream, arg);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS):
> +		retval = snd_compr_get_codec_caps(stream, arg);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS):
> +		retval = snd_compr_set_params(stream, arg);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_GET_PARAMS):
> +		retval = snd_compr_get_params(stream, arg);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_TSTAMP):
> +		retval = snd_compr_tstamp(stream, arg);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_AVAIL):
> +		retval = snd_compr_ioctl_avail(stream, arg);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_PAUSE):
> +		retval = snd_compr_pause(stream);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_RESUME):
> +		retval = snd_compr_resume(stream);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_START):
> +		retval = snd_compr_start(stream);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_STOP):
> +		retval = snd_compr_stop(stream);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_DRAIN):
> +		cmd = SND_COMPR_TRIGGER_DRAIN;

What's this?

> +		retval = snd_compr_drain(stream);
> +		break;
> +	}
> +	mutex_unlock(&stream->device->lock);
> +	return retval;


thanks,

Takashi


More information about the Alsa-devel mailing list