Open Sound System |
Do you have problems with sound/audio application development? Don't panic! Click here for help! |
void (*adrv_trigger) (int dev, int state);
The first paramater (dev
) is anways the audio engine number which is an index to the audio_engines table. The driver can use the audio_engines entry to find out some of the current parameters. In particular the devc, portc, portc_play and portc_record fields can be used to locate the driver defined structures for the audio engine.
The trigger method is probably the most complicated audio driver method. Great care must be taken when implementing it.
Purpose of this audio driver method is to actually start or stop recording and/or playback. The state
parameter tells which directions should be enabled (PCM_ENABLE_INPUT and/or PCM_ENABLE_OUTPUT). However the driver is required to do rather complex management to make sure that only the desired direction is affected.
The PCM_ENABLE_INPUT macro is defined to have the same value as the OPEN_READ macro. The same is true with PCM_ENABLE_OUTPUT and OPEN_WRITE. This means that the mode
parameter of adrv_open is "bit compatible" the state
parameter of this function. This makes it possible to do logical bit operations on these parameters.
The trigger method is NOT used to implement pause/resume. Instead it will get called in three possible situations:
After playback and/or recording has been stopped it's not permitted to let the stopped operation(s) to be triggered again before the corresponding adrv_prepare_for_* method has been called. In addition playback/recording must be started from the beginning of the DMA buffer instead of the position it was stopped.
The idea of the trigger method is to be able to start both recording and playback exactly on the same "clock tick". If the device has single register with enable/disable bits for both directions then both directions should get enabled at the end of the trigger method by a single write to this register.
If there are two registers to then they should be written in as atomic way as possible. The driver should not do unnecessary initializations between these writes. In addition local interrupts should be disabled before the writes (between MUTEX_ENTER_IRQDISABLE and MUTEX_EXIT_IRQRESTORE calls. In addition the whole trigger method should be designed to run as quickly as possible. Everything that could be done in the adrv_prepare_for_ methods should be done there.
Both recording and playback will be started simultaneously only if the application uses SNDCTL_DSP_SETTRIGGER to start both operations at the same time. However normal applications may start one direction before another. It is also possible than when the first direction is started the second one has not been initalized yet (by calling the corresponding adrv_prepare_for_* method).
Another not so easy situation is when two separate device files are used for recording and playback. In this case adrv_trigger called on the playback device file must not affect the recording direction (and vice versa).
These two special cases make management of adrv_trigger bit complicated. There are few checks the trigger method needs to do:
Recording or playback must not be triggered off if it's currently not triggered on. The driver needs to maintain a status variable for this.
As an example you can look how the oss_ich/oss_ich.c handles trigger.
The new syncronization group mechanism of OSS4 (SNDCTL_DSP_SYNCGROUP and SNDCTL_DSP_SYNCSTART) can be used to trigger multiple devices on multiple sound cards at the same time. For this reason drivers for devices that have independent inputs and outputs should also implement the adrv_sync_control method. In particular this is true with "professional" audio devices that may have multiple independent inputs and outputs. The audio core can emulate synchronization groups by calling adrv_trigger for each device but in this way the timing precision may not be best possible.
Audio driver entry point should return 0 if the call was successful. Negative return value (-errno) means that an error has occurred. However some of the functions have void type and they don't return any value.
audio/oss_audio_core.c | Audio core functionality of OSS |
include/ossddk.h | Source file oss-current/kernel/framework/include/ossddk/ossddk.h |
remux/oss_remux.c | Multi channel playback support for devices with multiple stereo engines. |
mixer/oss_mixer_core.c | OSS mixer core. |