unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait) { struct ivtv_open_id *id = filp->private_data; struct ivtv *itv = id->itv; struct ivtv_stream *s = &itv->streams[id->type]; int eof = test_bit(IVTV_F_S_STREAMOFF, &s->s_flags); /* Start a capture if there is none */ if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { int rc; mutex_lock(&itv->serialize_lock); rc = ivtv_start_capture(id); mutex_unlock(&itv->serialize_lock); if (rc) { IVTV_DEBUG_INFO("Could not start capture for %s (%d)\n", s->name, rc); return POLLERR; } IVTV_DEBUG_FILE("Encoder poll started capture\n"); } /* add stream's waitq to the poll list */ IVTV_DEBUG_HI_FILE("Encoder poll\n"); poll_wait(filp, &s->waitq, wait); if (eof || s->q_full.length) return POLLIN | POLLRDNORM; return 0; }
__poll_t ivtv_v4l2_dec_poll(struct file *filp, poll_table *wait) { struct ivtv_open_id *id = fh2id(filp->private_data); struct ivtv *itv = id->itv; struct ivtv_stream *s = &itv->streams[id->type]; __poll_t res = 0; /* add stream's waitq to the poll list */ IVTV_DEBUG_HI_FILE("Decoder poll\n"); /* If there are subscribed events, then only use the new event API instead of the old video.h based API. */ if (!list_empty(&id->fh.subscribed)) { poll_wait(filp, &id->fh.wait, wait); /* Turn off the old-style vsync events */ clear_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags); if (v4l2_event_pending(&id->fh)) res = EPOLLPRI; } else { /* This is the old-style API which is here only for backwards compatibility. */ poll_wait(filp, &s->waitq, wait); set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags); if (test_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags) || test_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags)) res = EPOLLPRI; } /* Allow write if buffers are available for writing */ if (s->q_free.buffers) res |= EPOLLOUT | EPOLLWRNORM; return res; }
static ssize_t ivtv_read_pos(struct ivtv_stream *s, char __user *ubuf, size_t count, loff_t *pos, int non_block) { ssize_t rc = count ? ivtv_read(s, ubuf, count, non_block) : 0; struct ivtv *itv = s->itv; IVTV_DEBUG_HI_FILE("read %zd from %s, got %zd\n", count, s->name, rc); if (rc > 0) pos += rc; return rc; }
ssize_t ivtv_v4l2_read(struct file * filp, char __user *buf, size_t count, loff_t * pos) { struct ivtv_open_id *id = fh2id(filp->private_data); struct ivtv *itv = id->itv; struct ivtv_stream *s = &itv->streams[id->type]; int rc; IVTV_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name); rc = ivtv_start_capture(id); if (rc) return rc; return ivtv_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK); }
ssize_t ivtv_v4l2_read(struct file * filp, char __user *buf, size_t count, loff_t * pos) { struct ivtv_open_id *id = fh2id(filp->private_data); struct ivtv *itv = id->itv; struct ivtv_stream *s = &itv->streams[id->type]; ssize_t rc; IVTV_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name); if (mutex_lock_interruptible(&itv->serialize_lock)) return -ERESTARTSYS; rc = ivtv_start_capture(id); if (!rc) rc = ivtv_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK); mutex_unlock(&itv->serialize_lock); return rc; }
unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table *wait) { struct ivtv_open_id *id = filp->private_data; struct ivtv *itv = id->itv; struct ivtv_stream *s = &itv->streams[id->type]; int res = 0; /* add stream's waitq to the poll list */ IVTV_DEBUG_HI_FILE("Decoder poll\n"); poll_wait(filp, &s->waitq, wait); set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags); if (test_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags) || test_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags)) res = POLLPRI; /* Allow write if buffers are available for writing */ if (s->q_free.buffers) res |= POLLOUT | POLLWRNORM; return res; }
__poll_t ivtv_v4l2_enc_poll(struct file *filp, poll_table *wait) { __poll_t req_events = poll_requested_events(wait); struct ivtv_open_id *id = fh2id(filp->private_data); struct ivtv *itv = id->itv; struct ivtv_stream *s = &itv->streams[id->type]; int eof = test_bit(IVTV_F_S_STREAMOFF, &s->s_flags); __poll_t res = 0; /* Start a capture if there is none */ if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags) && s->type != IVTV_ENC_STREAM_TYPE_RAD && (req_events & (EPOLLIN | EPOLLRDNORM))) { int rc; mutex_lock(&itv->serialize_lock); rc = ivtv_start_capture(id); mutex_unlock(&itv->serialize_lock); if (rc) { IVTV_DEBUG_INFO("Could not start capture for %s (%d)\n", s->name, rc); return EPOLLERR; } IVTV_DEBUG_FILE("Encoder poll started capture\n"); } /* add stream's waitq to the poll list */ IVTV_DEBUG_HI_FILE("Encoder poll\n"); poll_wait(filp, &s->waitq, wait); if (v4l2_event_pending(&id->fh)) res |= EPOLLPRI; else poll_wait(filp, &id->fh.wait, wait); if (s->q_full.length || s->q_io.length) return res | EPOLLIN | EPOLLRDNORM; if (eof) return res | EPOLLHUP; return res; }
static ssize_t ivtv_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *pos) { struct ivtv_open_id *id = fh2id(filp->private_data); struct ivtv *itv = id->itv; struct ivtv_stream *s = &itv->streams[id->type]; struct yuv_playback_info *yi = &itv->yuv_info; struct ivtv_buffer *buf; struct ivtv_queue q; int bytes_written = 0; int mode; int rc; DEFINE_WAIT(wait); IVTV_DEBUG_HI_FILE("write %zd bytes to %s\n", count, s->name); if (s->type != IVTV_DEC_STREAM_TYPE_MPG && s->type != IVTV_DEC_STREAM_TYPE_YUV && s->type != IVTV_DEC_STREAM_TYPE_VOUT) /* not decoder streams */ return -EINVAL; /* Try to claim this stream */ if (ivtv_claim_stream(id, s->type)) return -EBUSY; /* This stream does not need to start any decoding */ if (s->type == IVTV_DEC_STREAM_TYPE_VOUT) { int elems = count / sizeof(struct v4l2_sliced_vbi_data); set_bit(IVTV_F_S_APPL_IO, &s->s_flags); return ivtv_write_vbi_from_user(itv, (const struct v4l2_sliced_vbi_data __user *)user_buf, elems); } mode = s->type == IVTV_DEC_STREAM_TYPE_MPG ? OUT_MPG : OUT_YUV; if (ivtv_set_output_mode(itv, mode) != mode) { ivtv_release_stream(s); return -EBUSY; } ivtv_queue_init(&q); set_bit(IVTV_F_S_APPL_IO, &s->s_flags); /* Start decoder (returns 0 if already started) */ rc = ivtv_start_decoding(id, itv->speed); if (rc) { IVTV_DEBUG_WARN("Failed start decode stream %s\n", s->name); /* failure, clean up */ clear_bit(IVTV_F_S_STREAMING, &s->s_flags); clear_bit(IVTV_F_S_APPL_IO, &s->s_flags); return rc; } retry: /* If possible, just DMA the entire frame - Check the data transfer size since we may get here before the stream has been fully set-up */ if (mode == OUT_YUV && s->q_full.length == 0 && itv->dma_data_req_size) { while (count >= itv->dma_data_req_size) { rc = ivtv_yuv_udma_stream_frame(itv, (void __user *)user_buf); if (rc < 0) return rc; bytes_written += itv->dma_data_req_size; user_buf += itv->dma_data_req_size; count -= itv->dma_data_req_size; } if (count == 0) { IVTV_DEBUG_HI_FILE("Wrote %d bytes to %s (%d)\n", bytes_written, s->name, s->q_full.bytesused); return bytes_written; } } for (;;) { /* Gather buffers */ while (q.length - q.bytesused < count && (buf = ivtv_dequeue(s, &s->q_io))) ivtv_enqueue(s, buf, &q); while (q.length - q.bytesused < count && (buf = ivtv_dequeue(s, &s->q_free))) { ivtv_enqueue(s, buf, &q); } if (q.buffers) break; if (filp->f_flags & O_NONBLOCK) return -EAGAIN; mutex_unlock(&itv->serialize_lock); prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); /* New buffers might have become free before we were added to the waitqueue */ if (!s->q_free.buffers) schedule(); finish_wait(&s->waitq, &wait); mutex_lock(&itv->serialize_lock); if (signal_pending(current)) { IVTV_DEBUG_INFO("User stopped %s\n", s->name); return -EINTR; } } /* copy user data into buffers */ while ((buf = ivtv_dequeue(s, &q))) { /* yuv is a pain. Don't copy more data than needed for a single frame, otherwise we lose sync with the incoming stream */ if (s->type == IVTV_DEC_STREAM_TYPE_YUV && yi->stream_size + count > itv->dma_data_req_size) rc = ivtv_buf_copy_from_user(s, buf, user_buf, itv->dma_data_req_size - yi->stream_size); else rc = ivtv_buf_copy_from_user(s, buf, user_buf, count); /* Make sure we really got all the user data */ if (rc < 0) { ivtv_queue_move(s, &q, NULL, &s->q_free, 0); return rc; } user_buf += rc; count -= rc; bytes_written += rc; if (s->type == IVTV_DEC_STREAM_TYPE_YUV) { yi->stream_size += rc; /* If we have a complete yuv frame, break loop now */ if (yi->stream_size == itv->dma_data_req_size) { ivtv_enqueue(s, buf, &s->q_full); yi->stream_size = 0; break; } } if (buf->bytesused != s->buf_size) { /* incomplete, leave in q_io for next time */ ivtv_enqueue(s, buf, &s->q_io); break; } /* Byteswap MPEG buffer */ if (s->type == IVTV_DEC_STREAM_TYPE_MPG) ivtv_buf_swap(buf); ivtv_enqueue(s, buf, &s->q_full); } if (test_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags)) { if (s->q_full.length >= itv->dma_data_req_size) { int got_sig; if (mode == OUT_YUV) ivtv_yuv_setup_stream_frame(itv); mutex_unlock(&itv->serialize_lock); prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); while (!(got_sig = signal_pending(current)) && test_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) { schedule(); } finish_wait(&itv->dma_waitq, &wait); mutex_lock(&itv->serialize_lock); if (got_sig) { IVTV_DEBUG_INFO("User interrupted %s\n", s->name); return -EINTR; } clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags); ivtv_queue_move(s, &s->q_full, NULL, &s->q_predma, itv->dma_data_req_size); ivtv_dma_stream_dec_prepare(s, itv->dma_data_req_offset + IVTV_DECODER_OFFSET, 1); } } /* more user data is available, wait until buffers become free to transfer the rest. */ if (count && !(filp->f_flags & O_NONBLOCK)) goto retry; IVTV_DEBUG_HI_FILE("Wrote %d bytes to %s (%d)\n", bytes_written, s->name, s->q_full.bytesused); return bytes_written; }