static unsigned int snd_compr_poll(struct file *f, poll_table *wait) { struct snd_compr_file *data = f->private_data; struct snd_compr_stream *stream; size_t avail; int retval = 0; if (snd_BUG_ON(!data)) return -EFAULT; stream = &data->stream; if (snd_BUG_ON(!stream)) return -EFAULT; mutex_lock(&stream->device->lock); if (stream->runtime->state == SNDRV_PCM_STATE_PAUSED || stream->runtime->state == SNDRV_PCM_STATE_OPEN) { retval = -EBADFD; goto out; } poll_wait(f, &stream->runtime->sleep, wait); avail = snd_compr_get_avail(stream); pr_debug("avail is %ld\n", (unsigned long)avail); /* check if we have at least one fragment to fill */ switch (stream->runtime->state) { case SNDRV_PCM_STATE_DRAINING: /* stream has been woken up after drain is complete * draining done so set stream state to stopped */ retval = snd_compr_get_poll(stream); stream->runtime->state = SNDRV_PCM_STATE_SETUP; break; case SNDRV_PCM_STATE_RUNNING: case SNDRV_PCM_STATE_PREPARED: case SNDRV_PCM_STATE_PAUSED: if (avail >= stream->runtime->fragment_size) retval = snd_compr_get_poll(stream); break; default: if (stream->direction == SND_COMPRESS_PLAYBACK) retval = POLLOUT | POLLWRNORM | POLLERR; else retval = POLLIN | POLLRDNORM | POLLERR; break; } out: mutex_unlock(&stream->device->lock); return retval; }
static ssize_t snd_compr_read(struct file *f, char __user *buf, size_t count, loff_t *offset) { struct snd_compr_file *data = f->private_data; struct snd_compr_stream *stream; size_t avail; int retval; if (snd_BUG_ON(!data)) return -EFAULT; stream = &data->stream; mutex_lock(&stream->device->lock); /* read is allowed when stream is running, paused, draining and setup * (yes setup is state which we transition to after stop, so if user * wants to read data after stop we allow that) */ switch (stream->runtime->state) { case SNDRV_PCM_STATE_OPEN: case SNDRV_PCM_STATE_PREPARED: case SNDRV_PCM_STATE_SUSPENDED: case SNDRV_PCM_STATE_DISCONNECTED: retval = -EBADFD; goto out; case SNDRV_PCM_STATE_XRUN: retval = -EPIPE; goto out; } avail = snd_compr_get_avail(stream); pr_debug("avail returned %ld\n", (unsigned long)avail); /* calculate how much we can read from buffer */ if (avail > count) avail = count; if (stream->ops->copy) { retval = stream->ops->copy(stream, buf, avail); } else { retval = -ENXIO; goto out; } if (retval > 0) stream->runtime->total_bytes_transferred += retval; out: mutex_unlock(&stream->device->lock); return retval; }
static ssize_t snd_compr_write(struct file *f, const char __user *buf, size_t count, loff_t *offset) { struct snd_compr_file *data = f->private_data; struct snd_compr_stream *stream; size_t avail; int retval; if (snd_BUG_ON(!data)) return -EFAULT; stream = &data->stream; mutex_lock(&stream->device->lock); /* write is allowed when stream is running or has been steup */ switch (stream->runtime->state) { case SNDRV_PCM_STATE_SETUP: case SNDRV_PCM_STATE_PREPARED: case SNDRV_PCM_STATE_RUNNING: break; default: mutex_unlock(&stream->device->lock); return -EBADFD; } avail = snd_compr_get_avail(stream); pr_debug("avail returned %ld\n", (unsigned long)avail); /* calculate how much we can write to buffer */ if (avail > count) avail = count; if (stream->ops->copy) { char __user* cbuf = (char __user*)buf; retval = stream->ops->copy(stream, cbuf, avail); } else { retval = snd_compr_write_data(stream, buf, avail); } if (retval > 0) stream->runtime->total_bytes_available += retval; /* while initiating the stream, write should be called before START * call, so in setup move state */ if (stream->runtime->state == SNDRV_PCM_STATE_SETUP) { stream->runtime->state = SNDRV_PCM_STATE_PREPARED; pr_debug("stream prepared, Houston we are good to go\n"); } mutex_unlock(&stream->device->lock); return retval; }
static unsigned int snd_compr_poll(struct file *f, poll_table *wait) { struct snd_compr_file *data = f->private_data; struct snd_compr_stream *stream; size_t avail; int retval = 0; if (snd_BUG_ON(!data)) return -EFAULT; stream = &data->stream; if (snd_BUG_ON(!stream)) return -EFAULT; mutex_lock(&stream->device->lock); if (stream->runtime->state == SNDRV_PCM_STATE_PAUSED || stream->runtime->state == SNDRV_PCM_STATE_OPEN) { retval = -EBADFD; goto out; } poll_wait(f, &stream->runtime->sleep, wait); avail = snd_compr_get_avail(stream); pr_debug("avail is %zu\n", avail); switch (stream->runtime->state) { case SNDRV_PCM_STATE_DRAINING: retval = snd_compr_get_poll(stream); stream->runtime->state = SNDRV_PCM_STATE_SETUP; break; case SNDRV_PCM_STATE_RUNNING: case SNDRV_PCM_STATE_PREPARED: case SNDRV_PCM_STATE_PAUSED: if (avail >= stream->runtime->fragment_size) retval = snd_compr_get_poll(stream); break; default: if (stream->direction == SND_COMPRESS_PLAYBACK) retval = POLLOUT | POLLWRNORM | POLLERR; else retval = POLLIN | POLLRDNORM | POLLERR; break; } out: mutex_unlock(&stream->device->lock); return retval; }
static ssize_t snd_compr_write(struct file *f, const char __user *buf, size_t count, loff_t *offset) { struct snd_compr_file *data = f->private_data; struct snd_compr_stream *stream; size_t avail; int retval; if (snd_BUG_ON(!data)) return -EFAULT; stream = &data->stream; mutex_lock(&stream->device->lock); if (stream->runtime->state != SNDRV_PCM_STATE_SETUP && stream->runtime->state != SNDRV_PCM_STATE_RUNNING) { mutex_unlock(&stream->device->lock); return -EBADFD; } avail = snd_compr_get_avail(stream); pr_debug("avail returned %zu\n", avail); /* calculate how much we can write to buffer */ if (avail > count) avail = count; if (stream->ops->copy) { char __user* cbuf = (char __user*)buf; retval = stream->ops->copy(stream, cbuf, avail); } else { retval = snd_compr_write_data(stream, buf, avail); } if (retval > 0) stream->runtime->total_bytes_available += retval; if (stream->runtime->state == SNDRV_PCM_STATE_SETUP) { stream->runtime->state = SNDRV_PCM_STATE_PREPARED; pr_debug("stream prepared, Houston we are good to go\n"); } mutex_unlock(&stream->device->lock); return retval; }
static ssize_t snd_compr_read(struct file *f, char __user *buf, size_t count, loff_t *offset) { struct snd_compr_file *data = f->private_data; struct snd_compr_stream *stream; size_t avail; int retval; if (snd_BUG_ON(!data)) return -EFAULT; stream = &data->stream; mutex_lock(&stream->device->lock); switch (stream->runtime->state) { case SNDRV_PCM_STATE_OPEN: case SNDRV_PCM_STATE_PREPARED: case SNDRV_PCM_STATE_XRUN: case SNDRV_PCM_STATE_SUSPENDED: case SNDRV_PCM_STATE_DISCONNECTED: retval = -EBADFD; goto out; } avail = snd_compr_get_avail(stream); pr_debug("avail returned %zu\n", avail); if (avail > count) avail = count; if (stream->ops->copy) { retval = stream->ops->copy(stream, buf, avail); } else { retval = -ENXIO; goto out; } if (retval > 0) stream->runtime->total_bytes_transferred += retval; out: mutex_unlock(&stream->device->lock); return retval; }
static ssize_t snd_compr_read(struct file *f, char __user *buf, size_t count, loff_t *offset) { struct snd_compr_file *data = f->private_data; struct snd_compr_stream *stream; size_t avail; int retval; if (snd_BUG_ON(!data)) return -EFAULT; stream = &data->stream; mutex_lock(&stream->device->lock); /* read is allowed when stream is running */ if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING) { retval = -EBADFD; goto out; } avail = snd_compr_get_avail(stream); pr_debug("avail returned %ld\n", (unsigned long)avail); /* calculate how much we can read from buffer */ if (avail > count) avail = count; if (stream->ops->copy) { retval = stream->ops->copy(stream, buf, avail); } else { retval = -ENXIO; goto out; } if (retval > 0) stream->runtime->total_bytes_transferred += retval; out: mutex_unlock(&stream->device->lock); return retval; }