aboutsummaryrefslogtreecommitdiffstats
path: root/pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'pcm.c')
-rw-r--r--pcm.c35
1 files changed, 30 insertions, 5 deletions
diff --git a/pcm.c b/pcm.c
index 411db40..e91b121 100644
--- a/pcm.c
+++ b/pcm.c
@@ -67,6 +67,11 @@ static int pcm_open(struct snd_pcm_substream *substream)
struct snd_pcm_hardware *hw;
unsigned int chans = 0;
+ if (!snd_avirt_streams_sealed()) {
+ D_ERRORK("Cannot open PCM. Card is not sealed");
+ return -EPERM;
+ }
+
// Find the Audio Path mapped to this device
stream = snd_avirt_stream_find_by_device(substream->pcm->device);
if (IS_ERR_VALUE(stream) || !stream)
@@ -84,6 +89,10 @@ static int pcm_open(struct snd_pcm_substream *substream)
// Setup remaining hw properties
chans = stream->channels;
+ if (chans == 0) {
+ D_ERRORK("Channels cannot be 0");
+ return -EINVAL;
+ }
hw->channels_min = chans;
hw->channels_max = chans;
@@ -92,6 +101,22 @@ static int pcm_open(struct snd_pcm_substream *substream)
}
/**
+ * pcm_close - Implements 'close' callback for PCM middle layer
+ * @substream: pointer to ALSA PCM substream
+ *
+ * This is called when a PCM substream is closed.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int pcm_close(struct snd_pcm_substream *substream)
+{
+ // Do additional Audio Path 'close' callback
+ return DO_AUDIOPATH_CB(
+ (struct snd_avirt_audiopath *)PRIVATE_DATA(substream)->audiopath,
+ close, substream);
+}
+
+/**
* pcm_hw_params - Implements 'hw_params' callback for PCM middle layer
* @substream: pointer to ALSA PCM substream
* @hw_params: contains the hardware parameters for the PCM
@@ -105,7 +130,6 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
{
int retval;
- size_t bufsz;
/* Check supported channels */
if ((params_channels(hw_params) <
@@ -117,10 +141,8 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- bufsz = params_buffer_bytes(hw_params) *
- substream->runtime->hw.periods_max;
-
- retval = snd_pcm_lib_alloc_vmalloc_buffer(substream, bufsz);
+ retval = snd_pcm_lib_alloc_vmalloc_buffer(
+ substream, params_buffer_bytes(hw_params));
if (retval < 0)
D_ERRORK("pcm: buffer allocation failed: %d", retval);
@@ -144,6 +166,8 @@ static int pcm_hw_free(struct snd_pcm_substream *substream)
err = DO_AUDIOPATH_CB(
(struct snd_avirt_audiopath *)PRIVATE_DATA(substream)->audiopath,
hw_free, substream);
+ if (err < 0)
+ return err;
return snd_pcm_lib_free_vmalloc_buffer(substream);
}
@@ -154,6 +178,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream)
*/
struct snd_pcm_ops pcm_ops_avirt = {
.open = pcm_open,
+ .close = pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = pcm_hw_params,
.hw_free = pcm_hw_free,