ALSA provides an easy interface for procfs. The proc files are
very useful for debugging. I recommend you set up proc files if
you write a driver and want to get a running status or register
dumps. The API is found in
<sound/info.h>
.
To create a proc file, call
snd_card_proc_new()
.
struct snd_info_entry *entry; int err = snd_card_proc_new(card, "my-file", &entry);
where the second argument specifies the name of the proc file to be
created. The above example will create a file
my-file
under the card directory,
e.g. /proc/asound/card0/my-file
.
Like other components, the proc entry created via
snd_card_proc_new()
will be registered and
released automatically in the card registration and release
functions.
When the creation is successful, the function stores a new
instance in the pointer given in the third argument.
It is initialized as a text proc file for read only. To use
this proc file as a read-only text file as it is, set the read
callback with a private data via
snd_info_set_text_ops()
.
snd_info_set_text_ops(entry, chip, my_proc_read);
where the second argument (chip
) is the
private data to be used in the callbacks. The third parameter
specifies the read buffer size and the fourth
(my_proc_read
) is the callback function, which
is defined like
static void my_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer);
In the read callback, use snd_iprintf()
for
output strings, which works just like normal
printf()
. For example,
static void my_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { struct my_chip *chip = entry->private_data; snd_iprintf(buffer, "This is my chip!\n"); snd_iprintf(buffer, "Port = %ld\n", chip->port); }
The file permissions can be changed afterwards. As default, it's set as read only for all users. If you want to add write permission for the user (root as default), do as follows:
entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
and set the write buffer size and the callback
entry->c.text.write = my_proc_write;
For the write callback, you can use
snd_info_get_line()
to get a text line, and
snd_info_get_str()
to retrieve a string from
the line. Some examples are found in
core/oss/mixer_oss.c
, core/oss/and
pcm_oss.c
.
For a raw-data proc-file, set the attributes as follows:
static struct snd_info_entry_ops my_file_io_ops = { .read = my_file_io_read, }; entry->content = SNDRV_INFO_CONTENT_DATA; entry->private_data = chip; entry->c.ops = &my_file_io_ops; entry->size = 4096; entry->mode = S_IFREG | S_IRUGO;
The callback is much more complicated than the text-file
version. You need to use a low-level I/O functions such as
copy_from/to_user()
to transfer the
data.
static long my_file_io_read(struct snd_info_entry *entry, void *file_private_data, struct file *file, char *buf, unsigned long count, unsigned long pos) { long size = count; if (pos + size > local_max_size) size = local_max_size - pos; if (copy_to_user(buf, local_data + pos, size)) return -EFAULT; return size; }