162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * 362306a36Sopenharmony_ci * dvb_ringbuffer.h: ring buffer implementation for the dvb driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2003 Oliver Endriss 662306a36Sopenharmony_ci * Copyright (C) 2004 Andrew de Quincey 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * based on code originally found in av7110.c & dvb_ci.c: 962306a36Sopenharmony_ci * Copyright (C) 1999-2003 Ralph Metzler & Marcus Metzler 1062306a36Sopenharmony_ci * for convergence integrated media GmbH 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * This program is free software; you can redistribute it and/or 1362306a36Sopenharmony_ci * modify it under the terms of the GNU Lesser General Public License 1462306a36Sopenharmony_ci * as published by the Free Software Foundation; either version 2.1 1562306a36Sopenharmony_ci * of the License, or (at your option) any later version. 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci * This program is distributed in the hope that it will be useful, 1862306a36Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 1962306a36Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 2062306a36Sopenharmony_ci * GNU Lesser General Public License for more details. 2162306a36Sopenharmony_ci */ 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#ifndef _DVB_RINGBUFFER_H_ 2462306a36Sopenharmony_ci#define _DVB_RINGBUFFER_H_ 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#include <linux/spinlock.h> 2762306a36Sopenharmony_ci#include <linux/wait.h> 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci/** 3062306a36Sopenharmony_ci * struct dvb_ringbuffer - Describes a ring buffer used at DVB framework 3162306a36Sopenharmony_ci * 3262306a36Sopenharmony_ci * @data: Area were the ringbuffer data is written 3362306a36Sopenharmony_ci * @size: size of the ringbuffer 3462306a36Sopenharmony_ci * @pread: next position to read 3562306a36Sopenharmony_ci * @pwrite: next position to write 3662306a36Sopenharmony_ci * @error: used by ringbuffer clients to indicate that an error happened. 3762306a36Sopenharmony_ci * @queue: Wait queue used by ringbuffer clients to indicate when buffer 3862306a36Sopenharmony_ci * was filled 3962306a36Sopenharmony_ci * @lock: Spinlock used to protect the ringbuffer 4062306a36Sopenharmony_ci */ 4162306a36Sopenharmony_cistruct dvb_ringbuffer { 4262306a36Sopenharmony_ci u8 *data; 4362306a36Sopenharmony_ci ssize_t size; 4462306a36Sopenharmony_ci ssize_t pread; 4562306a36Sopenharmony_ci ssize_t pwrite; 4662306a36Sopenharmony_ci int error; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci wait_queue_head_t queue; 4962306a36Sopenharmony_ci spinlock_t lock; 5062306a36Sopenharmony_ci}; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci#define DVB_RINGBUFFER_PKTHDRSIZE 3 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci/** 5562306a36Sopenharmony_ci * dvb_ringbuffer_init - initialize ring buffer, lock and queue 5662306a36Sopenharmony_ci * 5762306a36Sopenharmony_ci * @rbuf: pointer to struct dvb_ringbuffer 5862306a36Sopenharmony_ci * @data: pointer to the buffer where the data will be stored 5962306a36Sopenharmony_ci * @len: bytes from ring buffer into @buf 6062306a36Sopenharmony_ci */ 6162306a36Sopenharmony_ciextern void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, 6262306a36Sopenharmony_ci size_t len); 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci/** 6562306a36Sopenharmony_ci * dvb_ringbuffer_empty - test whether buffer is empty 6662306a36Sopenharmony_ci * 6762306a36Sopenharmony_ci * @rbuf: pointer to struct dvb_ringbuffer 6862306a36Sopenharmony_ci */ 6962306a36Sopenharmony_ciextern int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf); 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci/** 7262306a36Sopenharmony_ci * dvb_ringbuffer_free - returns the number of free bytes in the buffer 7362306a36Sopenharmony_ci * 7462306a36Sopenharmony_ci * @rbuf: pointer to struct dvb_ringbuffer 7562306a36Sopenharmony_ci * 7662306a36Sopenharmony_ci * Return: number of free bytes in the buffer 7762306a36Sopenharmony_ci */ 7862306a36Sopenharmony_ciextern ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf); 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci/** 8162306a36Sopenharmony_ci * dvb_ringbuffer_avail - returns the number of bytes waiting in the buffer 8262306a36Sopenharmony_ci * 8362306a36Sopenharmony_ci * @rbuf: pointer to struct dvb_ringbuffer 8462306a36Sopenharmony_ci * 8562306a36Sopenharmony_ci * Return: number of bytes waiting in the buffer 8662306a36Sopenharmony_ci */ 8762306a36Sopenharmony_ciextern ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf); 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci/** 9062306a36Sopenharmony_ci * dvb_ringbuffer_reset - resets the ringbuffer to initial state 9162306a36Sopenharmony_ci * 9262306a36Sopenharmony_ci * @rbuf: pointer to struct dvb_ringbuffer 9362306a36Sopenharmony_ci * 9462306a36Sopenharmony_ci * Resets the read and write pointers to zero and flush the buffer. 9562306a36Sopenharmony_ci * 9662306a36Sopenharmony_ci * This counts as a read and write operation 9762306a36Sopenharmony_ci */ 9862306a36Sopenharmony_ciextern void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf); 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci/* 10162306a36Sopenharmony_ci * read routines & macros 10262306a36Sopenharmony_ci */ 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci/** 10562306a36Sopenharmony_ci * dvb_ringbuffer_flush - flush buffer 10662306a36Sopenharmony_ci * 10762306a36Sopenharmony_ci * @rbuf: pointer to struct dvb_ringbuffer 10862306a36Sopenharmony_ci */ 10962306a36Sopenharmony_ciextern void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci/** 11262306a36Sopenharmony_ci * dvb_ringbuffer_flush_spinlock_wakeup- flush buffer protected by spinlock 11362306a36Sopenharmony_ci * and wake-up waiting task(s) 11462306a36Sopenharmony_ci * 11562306a36Sopenharmony_ci * @rbuf: pointer to struct dvb_ringbuffer 11662306a36Sopenharmony_ci */ 11762306a36Sopenharmony_ciextern void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci/** 12062306a36Sopenharmony_ci * DVB_RINGBUFFER_PEEK - peek at byte @offs in the buffer 12162306a36Sopenharmony_ci * 12262306a36Sopenharmony_ci * @rbuf: pointer to struct dvb_ringbuffer 12362306a36Sopenharmony_ci * @offs: offset inside the ringbuffer 12462306a36Sopenharmony_ci */ 12562306a36Sopenharmony_ci#define DVB_RINGBUFFER_PEEK(rbuf, offs) \ 12662306a36Sopenharmony_ci ((rbuf)->data[((rbuf)->pread + (offs)) % (rbuf)->size]) 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci/** 12962306a36Sopenharmony_ci * DVB_RINGBUFFER_SKIP - advance read ptr by @num bytes 13062306a36Sopenharmony_ci * 13162306a36Sopenharmony_ci * @rbuf: pointer to struct dvb_ringbuffer 13262306a36Sopenharmony_ci * @num: number of bytes to advance 13362306a36Sopenharmony_ci */ 13462306a36Sopenharmony_ci#define DVB_RINGBUFFER_SKIP(rbuf, num) {\ 13562306a36Sopenharmony_ci (rbuf)->pread = ((rbuf)->pread + (num)) % (rbuf)->size;\ 13662306a36Sopenharmony_ci} 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci/** 13962306a36Sopenharmony_ci * dvb_ringbuffer_read_user - Reads a buffer into a user pointer 14062306a36Sopenharmony_ci * 14162306a36Sopenharmony_ci * @rbuf: pointer to struct dvb_ringbuffer 14262306a36Sopenharmony_ci * @buf: pointer to the buffer where the data will be stored 14362306a36Sopenharmony_ci * @len: bytes from ring buffer into @buf 14462306a36Sopenharmony_ci * 14562306a36Sopenharmony_ci * This variant assumes that the buffer is a memory at the userspace. So, 14662306a36Sopenharmony_ci * it will internally call copy_to_user(). 14762306a36Sopenharmony_ci * 14862306a36Sopenharmony_ci * Return: number of bytes transferred or -EFAULT 14962306a36Sopenharmony_ci */ 15062306a36Sopenharmony_ciextern ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, 15162306a36Sopenharmony_ci u8 __user *buf, size_t len); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci/** 15462306a36Sopenharmony_ci * dvb_ringbuffer_read - Reads a buffer into a pointer 15562306a36Sopenharmony_ci * 15662306a36Sopenharmony_ci * @rbuf: pointer to struct dvb_ringbuffer 15762306a36Sopenharmony_ci * @buf: pointer to the buffer where the data will be stored 15862306a36Sopenharmony_ci * @len: bytes from ring buffer into @buf 15962306a36Sopenharmony_ci * 16062306a36Sopenharmony_ci * This variant assumes that the buffer is a memory at the Kernel space 16162306a36Sopenharmony_ci * 16262306a36Sopenharmony_ci * Return: number of bytes transferred or -EFAULT 16362306a36Sopenharmony_ci */ 16462306a36Sopenharmony_ciextern void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, 16562306a36Sopenharmony_ci u8 *buf, size_t len); 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci/* 16862306a36Sopenharmony_ci * write routines & macros 16962306a36Sopenharmony_ci */ 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci/** 17262306a36Sopenharmony_ci * DVB_RINGBUFFER_WRITE_BYTE - write single byte to ring buffer 17362306a36Sopenharmony_ci * 17462306a36Sopenharmony_ci * @rbuf: pointer to struct dvb_ringbuffer 17562306a36Sopenharmony_ci * @byte: byte to write 17662306a36Sopenharmony_ci */ 17762306a36Sopenharmony_ci#define DVB_RINGBUFFER_WRITE_BYTE(rbuf, byte) \ 17862306a36Sopenharmony_ci { (rbuf)->data[(rbuf)->pwrite] = (byte); \ 17962306a36Sopenharmony_ci (rbuf)->pwrite = ((rbuf)->pwrite + 1) % (rbuf)->size; } 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci/** 18262306a36Sopenharmony_ci * dvb_ringbuffer_write - Writes a buffer into the ringbuffer 18362306a36Sopenharmony_ci * 18462306a36Sopenharmony_ci * @rbuf: pointer to struct dvb_ringbuffer 18562306a36Sopenharmony_ci * @buf: pointer to the buffer where the data will be read 18662306a36Sopenharmony_ci * @len: bytes from ring buffer into @buf 18762306a36Sopenharmony_ci * 18862306a36Sopenharmony_ci * This variant assumes that the buffer is a memory at the Kernel space 18962306a36Sopenharmony_ci * 19062306a36Sopenharmony_ci * return: number of bytes transferred or -EFAULT 19162306a36Sopenharmony_ci */ 19262306a36Sopenharmony_ciextern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, 19362306a36Sopenharmony_ci size_t len); 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci/** 19662306a36Sopenharmony_ci * dvb_ringbuffer_write_user - Writes a buffer received via a user pointer 19762306a36Sopenharmony_ci * 19862306a36Sopenharmony_ci * @rbuf: pointer to struct dvb_ringbuffer 19962306a36Sopenharmony_ci * @buf: pointer to the buffer where the data will be read 20062306a36Sopenharmony_ci * @len: bytes from ring buffer into @buf 20162306a36Sopenharmony_ci * 20262306a36Sopenharmony_ci * This variant assumes that the buffer is a memory at the userspace. So, 20362306a36Sopenharmony_ci * it will internally call copy_from_user(). 20462306a36Sopenharmony_ci * 20562306a36Sopenharmony_ci * Return: number of bytes transferred or -EFAULT 20662306a36Sopenharmony_ci */ 20762306a36Sopenharmony_ciextern ssize_t dvb_ringbuffer_write_user(struct dvb_ringbuffer *rbuf, 20862306a36Sopenharmony_ci const u8 __user *buf, size_t len); 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci/** 21162306a36Sopenharmony_ci * dvb_ringbuffer_pkt_write - Write a packet into the ringbuffer. 21262306a36Sopenharmony_ci * 21362306a36Sopenharmony_ci * @rbuf: Ringbuffer to write to. 21462306a36Sopenharmony_ci * @buf: Buffer to write. 21562306a36Sopenharmony_ci * @len: Length of buffer (currently limited to 65535 bytes max). 21662306a36Sopenharmony_ci * 21762306a36Sopenharmony_ci * Return: Number of bytes written, or -EFAULT, -ENOMEM, -EINVAL. 21862306a36Sopenharmony_ci */ 21962306a36Sopenharmony_ciextern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8 *buf, 22062306a36Sopenharmony_ci size_t len); 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci/** 22362306a36Sopenharmony_ci * dvb_ringbuffer_pkt_read_user - Read from a packet in the ringbuffer. 22462306a36Sopenharmony_ci * 22562306a36Sopenharmony_ci * @rbuf: Ringbuffer concerned. 22662306a36Sopenharmony_ci * @idx: Packet index as returned by dvb_ringbuffer_pkt_next(). 22762306a36Sopenharmony_ci * @offset: Offset into packet to read from. 22862306a36Sopenharmony_ci * @buf: Destination buffer for data. 22962306a36Sopenharmony_ci * @len: Size of destination buffer. 23062306a36Sopenharmony_ci * 23162306a36Sopenharmony_ci * Return: Number of bytes read, or -EFAULT. 23262306a36Sopenharmony_ci * 23362306a36Sopenharmony_ci * .. note:: 23462306a36Sopenharmony_ci * 23562306a36Sopenharmony_ci * unlike dvb_ringbuffer_read(), this does **NOT** update the read pointer 23662306a36Sopenharmony_ci * in the ringbuffer. You must use dvb_ringbuffer_pkt_dispose() to mark a 23762306a36Sopenharmony_ci * packet as no longer required. 23862306a36Sopenharmony_ci */ 23962306a36Sopenharmony_ciextern ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, 24062306a36Sopenharmony_ci size_t idx, 24162306a36Sopenharmony_ci int offset, u8 __user *buf, 24262306a36Sopenharmony_ci size_t len); 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci/** 24562306a36Sopenharmony_ci * dvb_ringbuffer_pkt_read - Read from a packet in the ringbuffer. 24662306a36Sopenharmony_ci * Note: unlike dvb_ringbuffer_read_user(), this DOES update the read pointer 24762306a36Sopenharmony_ci * in the ringbuffer. 24862306a36Sopenharmony_ci * 24962306a36Sopenharmony_ci * @rbuf: Ringbuffer concerned. 25062306a36Sopenharmony_ci * @idx: Packet index as returned by dvb_ringbuffer_pkt_next(). 25162306a36Sopenharmony_ci * @offset: Offset into packet to read from. 25262306a36Sopenharmony_ci * @buf: Destination buffer for data. 25362306a36Sopenharmony_ci * @len: Size of destination buffer. 25462306a36Sopenharmony_ci * 25562306a36Sopenharmony_ci * Return: Number of bytes read, or -EFAULT. 25662306a36Sopenharmony_ci */ 25762306a36Sopenharmony_ciextern ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx, 25862306a36Sopenharmony_ci int offset, u8 *buf, size_t len); 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci/** 26162306a36Sopenharmony_ci * dvb_ringbuffer_pkt_dispose - Dispose of a packet in the ring buffer. 26262306a36Sopenharmony_ci * 26362306a36Sopenharmony_ci * @rbuf: Ring buffer concerned. 26462306a36Sopenharmony_ci * @idx: Packet index as returned by dvb_ringbuffer_pkt_next(). 26562306a36Sopenharmony_ci */ 26662306a36Sopenharmony_ciextern void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx); 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci/** 26962306a36Sopenharmony_ci * dvb_ringbuffer_pkt_next - Get the index of the next packet in a ringbuffer. 27062306a36Sopenharmony_ci * 27162306a36Sopenharmony_ci * @rbuf: Ringbuffer concerned. 27262306a36Sopenharmony_ci * @idx: Previous packet index, or -1 to return the first packet index. 27362306a36Sopenharmony_ci * @pktlen: On success, will be updated to contain the length of the packet 27462306a36Sopenharmony_ci * in bytes. 27562306a36Sopenharmony_ci * returns Packet index (if >=0), or -1 if no packets available. 27662306a36Sopenharmony_ci */ 27762306a36Sopenharmony_ciextern ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, 27862306a36Sopenharmony_ci size_t idx, size_t *pktlen); 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci#endif /* _DVB_RINGBUFFER_H_ */ 281