This document describes the ALSA driver and kernel API. Application programmers should use the library API rather than kernel API. The ALSA Library offers 100% of the functionally of the kernel API, but add next major improvements in usability, making the application code simpler and better looking. In addition, some of the some fixes/compatibility code in, may be placed in the library code instead of the kernel driver.
Source files are separated to:
Directory contains all header files which are included from more sources.
Directory with kernel code and abstract layers (middle level code and library).
Generic lowlevel code for chip(set)s.
Upper level for soundcards and specific lowlevel code.
Detection layer (/proc/asound/detect - to make installation easy).
Devices should use abstract code from sound kernel, but it should use own code and register minors separetely (with snd_minor_register and snd_minor_unregister functions). This method totaly bypass all abstract code, so code for these soundcards must handle all things.
These routines use their own memory allocation algoritm. It should be removed in the future and replaced with kmalloc and kfree calls, but for now I need to trace all allocation problems to make code clean...
Note: ALSA driver heavily uses dynamic allocation for most things.
For debugging you should use command './configure --with-debug=full' for configuration. This enables trace of allocated memory with above functions and this makes debugging a little bit easier.
All things are made as objects (which encapsulates data and functions) and are referenced in this way. I don't prefer to pass index to some array of structure or something like this. Objects contain both data and functions. Pointers to these objects are passed around (like C++).
All main structures should have snd_xxxx_new, snd_xxxx_free, snd_xxxx_register, snd_xxxx_unregister functions.
Code for soundcards should contain these things:
Note: Due to module dependency you should separate code for soundcards from the same manufacture which have slightly different hardware. Example: The GUS Extreme has an ESS ES-1688 chip. This chip isn't in the GUS Classic. For GUS Classic, the generic code in the snd-es1688.o module isn't needed. So there are two upper level modules (snd-gusextreme.o and snd-gusclassic.o).
Some structures have pointers to private data and values. These variables aren't used with the abstract layers and are intended for low-level code use only.
snd_card_t -> private_data snd_card_t -> private_free (called from snd_card_free if not NULL)
struct snd_stru_pcm_hardware -> private_data struct snd_stru_pcm_hardware -> private_free (called from snd_pcm_free if not NULL) snd_pcm_t -> private_data snd_pcm_t -> private_free (called from snd_pcm_free if not NULL)
struct snd_stru_mixer_channel_hw -> private_value snd_kmixer_channel_t -> private_data snd_kmixer_channel_t -> private_free (called from snd_mixer_free if not NULL) snd_kmixer_t -> private_value snd_kmixer_t -> private_data snd_kmixer_t -> private_free (called from snd_mixer_free if not NULL)
Good code shouldn't contain snd_cli()/snd_sti() calls. Instead use spin locks snd_spin_lock()/snd_spin_unlock() for locking code. This method is much better for SMP machines.
Note: Debugging code is available for locking. Look in sndspinlock.h to enable it.
You should look at the code for GUS soundcards to see how can be things done...
Note: Code should be compiled cleanly under 2.0.X kernels and under latest 2.1.X kernels...