static ssize_t ci_ll_read(struct dvb_ringbuffer *cibuf, struct file *file, char __user *buf, size_t count, loff_t *ppos) { int avail; int non_blocking = file->f_flags & O_NONBLOCK; ssize_t len; if (!cibuf->data || !count) return 0; if (non_blocking && (dvb_ringbuffer_empty(cibuf))) return -EWOULDBLOCK; if (wait_event_interruptible(cibuf->queue, !dvb_ringbuffer_empty(cibuf))) return -ERESTARTSYS; avail = dvb_ringbuffer_avail(cibuf); if (avail < 4) return 0; len = DVB_RINGBUFFER_PEEK(cibuf, 0) << 8; len |= DVB_RINGBUFFER_PEEK(cibuf, 1); if (avail < len + 2 || count < len) return -EINVAL; DVB_RINGBUFFER_SKIP(cibuf, 2); return dvb_ringbuffer_read_user(cibuf, buf, len); }
int mpq_streambuffer_data_read_dispose( struct mpq_streambuffer *sbuff, size_t len) { if (NULL == sbuff) return -EINVAL; if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode) { if (unlikely(dvb_ringbuffer_avail(&sbuff->raw_data) < len)) return -EINVAL; DVB_RINGBUFFER_SKIP(&sbuff->raw_data, len); wake_up_all(&sbuff->raw_data.queue); } else { struct mpq_streambuffer_buffer_desc *desc; desc = (struct mpq_streambuffer_buffer_desc *) &sbuff->raw_data.data[sbuff->raw_data.pread]; if ((desc->read_ptr + len) > desc->size) desc->read_ptr = desc->size; else desc->read_ptr += len; } return 0; }
int mpq_streambuffer_pkt_dispose( struct mpq_streambuffer *sbuff, size_t idx, int dispose_data) { int ret; struct mpq_streambuffer_packet_header packet; if (NULL == sbuff) return -EINVAL; /* read-out the packet header first */ ret = dvb_ringbuffer_pkt_read(&sbuff->packet_data, idx, 0, (u8 *)&packet, sizeof(struct mpq_streambuffer_packet_header)); if (ret != sizeof(struct mpq_streambuffer_packet_header)) return -EINVAL; if ((MPQ_STREAMBUFFER_BUFFER_MODE_LINEAR == sbuff->mode) || (dispose_data)) { /* Advance the read pointer in the raw-data buffer first */ ret = mpq_streambuffer_data_read_dispose(sbuff, packet.raw_data_len); if (ret != 0) return ret; } /* Move read pointer to the next linear buffer for subsequent reads */ if ((MPQ_STREAMBUFFER_BUFFER_MODE_LINEAR == sbuff->mode) && (packet.raw_data_len > 0)) { struct mpq_streambuffer_buffer_desc *desc; desc = (struct mpq_streambuffer_buffer_desc *) &sbuff->raw_data.data[sbuff->raw_data.pread]; desc->write_ptr = 0; desc->read_ptr = 0; DVB_RINGBUFFER_SKIP(&sbuff->raw_data, sizeof(struct mpq_streambuffer_buffer_desc)); sbuff->pending_buffers_count--; wake_up_all(&sbuff->raw_data.queue); } /* Now clear the packet from the packet header */ dvb_ringbuffer_pkt_dispose(&sbuff->packet_data, idx); if (sbuff->cb) sbuff->cb(sbuff, sbuff->cb_user_data); return 0; }
void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx) { size_t pktlen; rbuf->data[(idx + 2) % rbuf->size] = PKT_DISPOSED; // clean up disposed packets while(dvb_ringbuffer_avail(rbuf) > DVB_RINGBUFFER_PKTHDRSIZE) { if (DVB_RINGBUFFER_PEEK(rbuf, 2) == PKT_DISPOSED) { pktlen = DVB_RINGBUFFER_PEEK(rbuf, 0) << 8; pktlen |= DVB_RINGBUFFER_PEEK(rbuf, 1); DVB_RINGBUFFER_SKIP(rbuf, pktlen + DVB_RINGBUFFER_PKTHDRSIZE); } else { // first packet is not disposed, so we stop cleaning now break; } } }