18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * 38c2ecf20Sopenharmony_ci * dvb_ringbuffer.h: ring buffer implementation for the dvb driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2003 Oliver Endriss 68c2ecf20Sopenharmony_ci * Copyright (C) 2004 Andrew de Quincey 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * based on code originally found in av7110.c & dvb_ci.c: 98c2ecf20Sopenharmony_ci * Copyright (C) 1999-2003 Ralph Metzler & Marcus Metzler 108c2ecf20Sopenharmony_ci * for convergence integrated media GmbH 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or 138c2ecf20Sopenharmony_ci * modify it under the terms of the GNU Lesser General Public License 148c2ecf20Sopenharmony_ci * as published by the Free Software Foundation; either version 2.1 158c2ecf20Sopenharmony_ci * of the License, or (at your option) any later version. 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * This program is distributed in the hope that it will be useful, 188c2ecf20Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 198c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 208c2ecf20Sopenharmony_ci * GNU Lesser General Public License for more details. 218c2ecf20Sopenharmony_ci */ 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#ifndef _DVB_RINGBUFFER_H_ 248c2ecf20Sopenharmony_ci#define _DVB_RINGBUFFER_H_ 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 278c2ecf20Sopenharmony_ci#include <linux/wait.h> 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci/** 308c2ecf20Sopenharmony_ci * struct dvb_ringbuffer - Describes a ring buffer used at DVB framework 318c2ecf20Sopenharmony_ci * 328c2ecf20Sopenharmony_ci * @data: Area were the ringbuffer data is written 338c2ecf20Sopenharmony_ci * @size: size of the ringbuffer 348c2ecf20Sopenharmony_ci * @pread: next position to read 358c2ecf20Sopenharmony_ci * @pwrite: next position to write 368c2ecf20Sopenharmony_ci * @error: used by ringbuffer clients to indicate that an error happened. 378c2ecf20Sopenharmony_ci * @queue: Wait queue used by ringbuffer clients to indicate when buffer 388c2ecf20Sopenharmony_ci * was filled 398c2ecf20Sopenharmony_ci * @lock: Spinlock used to protect the ringbuffer 408c2ecf20Sopenharmony_ci */ 418c2ecf20Sopenharmony_cistruct dvb_ringbuffer { 428c2ecf20Sopenharmony_ci u8 *data; 438c2ecf20Sopenharmony_ci ssize_t size; 448c2ecf20Sopenharmony_ci ssize_t pread; 458c2ecf20Sopenharmony_ci ssize_t pwrite; 468c2ecf20Sopenharmony_ci int error; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci wait_queue_head_t queue; 498c2ecf20Sopenharmony_ci spinlock_t lock; 508c2ecf20Sopenharmony_ci}; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci#define DVB_RINGBUFFER_PKTHDRSIZE 3 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci/** 558c2ecf20Sopenharmony_ci * dvb_ringbuffer_init - initialize ring buffer, lock and queue 568c2ecf20Sopenharmony_ci * 578c2ecf20Sopenharmony_ci * @rbuf: pointer to struct dvb_ringbuffer 588c2ecf20Sopenharmony_ci * @data: pointer to the buffer where the data will be stored 598c2ecf20Sopenharmony_ci * @len: bytes from ring buffer into @buf 608c2ecf20Sopenharmony_ci */ 618c2ecf20Sopenharmony_ciextern void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, 628c2ecf20Sopenharmony_ci size_t len); 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci/** 658c2ecf20Sopenharmony_ci * dvb_ringbuffer_empty - test whether buffer is empty 668c2ecf20Sopenharmony_ci * 678c2ecf20Sopenharmony_ci * @rbuf: pointer to struct dvb_ringbuffer 688c2ecf20Sopenharmony_ci */ 698c2ecf20Sopenharmony_ciextern int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci/** 728c2ecf20Sopenharmony_ci * dvb_ringbuffer_free - returns the number of free bytes in the buffer 738c2ecf20Sopenharmony_ci * 748c2ecf20Sopenharmony_ci * @rbuf: pointer to struct dvb_ringbuffer 758c2ecf20Sopenharmony_ci * 768c2ecf20Sopenharmony_ci * Return: number of free bytes in the buffer 778c2ecf20Sopenharmony_ci */ 788c2ecf20Sopenharmony_ciextern ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf); 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci/** 818c2ecf20Sopenharmony_ci * dvb_ringbuffer_avail - returns the number of bytes waiting in the buffer 828c2ecf20Sopenharmony_ci * 838c2ecf20Sopenharmony_ci * @rbuf: pointer to struct dvb_ringbuffer 848c2ecf20Sopenharmony_ci * 858c2ecf20Sopenharmony_ci * Return: number of bytes waiting in the buffer 868c2ecf20Sopenharmony_ci */ 878c2ecf20Sopenharmony_ciextern ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf); 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci/** 908c2ecf20Sopenharmony_ci * dvb_ringbuffer_reset - resets the ringbuffer to initial state 918c2ecf20Sopenharmony_ci * 928c2ecf20Sopenharmony_ci * @rbuf: pointer to struct dvb_ringbuffer 938c2ecf20Sopenharmony_ci * 948c2ecf20Sopenharmony_ci * Resets the read and write pointers to zero and flush the buffer. 958c2ecf20Sopenharmony_ci * 968c2ecf20Sopenharmony_ci * This counts as a read and write operation 978c2ecf20Sopenharmony_ci */ 988c2ecf20Sopenharmony_ciextern void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf); 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci/* 1018c2ecf20Sopenharmony_ci * read routines & macros 1028c2ecf20Sopenharmony_ci */ 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci/** 1058c2ecf20Sopenharmony_ci * dvb_ringbuffer_flush - flush buffer 1068c2ecf20Sopenharmony_ci * 1078c2ecf20Sopenharmony_ci * @rbuf: pointer to struct dvb_ringbuffer 1088c2ecf20Sopenharmony_ci */ 1098c2ecf20Sopenharmony_ciextern void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf); 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci/** 1128c2ecf20Sopenharmony_ci * dvb_ringbuffer_flush_spinlock_wakeup- flush buffer protected by spinlock 1138c2ecf20Sopenharmony_ci * and wake-up waiting task(s) 1148c2ecf20Sopenharmony_ci * 1158c2ecf20Sopenharmony_ci * @rbuf: pointer to struct dvb_ringbuffer 1168c2ecf20Sopenharmony_ci */ 1178c2ecf20Sopenharmony_ciextern void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf); 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci/** 1208c2ecf20Sopenharmony_ci * DVB_RINGBUFFER_PEEK - peek at byte @offs in the buffer 1218c2ecf20Sopenharmony_ci * 1228c2ecf20Sopenharmony_ci * @rbuf: pointer to struct dvb_ringbuffer 1238c2ecf20Sopenharmony_ci * @offs: offset inside the ringbuffer 1248c2ecf20Sopenharmony_ci */ 1258c2ecf20Sopenharmony_ci#define DVB_RINGBUFFER_PEEK(rbuf, offs) \ 1268c2ecf20Sopenharmony_ci ((rbuf)->data[((rbuf)->pread + (offs)) % (rbuf)->size]) 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci/** 1298c2ecf20Sopenharmony_ci * DVB_RINGBUFFER_SKIP - advance read ptr by @num bytes 1308c2ecf20Sopenharmony_ci * 1318c2ecf20Sopenharmony_ci * @rbuf: pointer to struct dvb_ringbuffer 1328c2ecf20Sopenharmony_ci * @num: number of bytes to advance 1338c2ecf20Sopenharmony_ci */ 1348c2ecf20Sopenharmony_ci#define DVB_RINGBUFFER_SKIP(rbuf, num) {\ 1358c2ecf20Sopenharmony_ci (rbuf)->pread = ((rbuf)->pread + (num)) % (rbuf)->size;\ 1368c2ecf20Sopenharmony_ci} 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci/** 1398c2ecf20Sopenharmony_ci * dvb_ringbuffer_read_user - Reads a buffer into a user pointer 1408c2ecf20Sopenharmony_ci * 1418c2ecf20Sopenharmony_ci * @rbuf: pointer to struct dvb_ringbuffer 1428c2ecf20Sopenharmony_ci * @buf: pointer to the buffer where the data will be stored 1438c2ecf20Sopenharmony_ci * @len: bytes from ring buffer into @buf 1448c2ecf20Sopenharmony_ci * 1458c2ecf20Sopenharmony_ci * This variant assumes that the buffer is a memory at the userspace. So, 1468c2ecf20Sopenharmony_ci * it will internally call copy_to_user(). 1478c2ecf20Sopenharmony_ci * 1488c2ecf20Sopenharmony_ci * Return: number of bytes transferred or -EFAULT 1498c2ecf20Sopenharmony_ci */ 1508c2ecf20Sopenharmony_ciextern ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, 1518c2ecf20Sopenharmony_ci u8 __user *buf, size_t len); 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci/** 1548c2ecf20Sopenharmony_ci * dvb_ringbuffer_read - Reads a buffer into a pointer 1558c2ecf20Sopenharmony_ci * 1568c2ecf20Sopenharmony_ci * @rbuf: pointer to struct dvb_ringbuffer 1578c2ecf20Sopenharmony_ci * @buf: pointer to the buffer where the data will be stored 1588c2ecf20Sopenharmony_ci * @len: bytes from ring buffer into @buf 1598c2ecf20Sopenharmony_ci * 1608c2ecf20Sopenharmony_ci * This variant assumes that the buffer is a memory at the Kernel space 1618c2ecf20Sopenharmony_ci * 1628c2ecf20Sopenharmony_ci * Return: number of bytes transferred or -EFAULT 1638c2ecf20Sopenharmony_ci */ 1648c2ecf20Sopenharmony_ciextern void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, 1658c2ecf20Sopenharmony_ci u8 *buf, size_t len); 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci/* 1688c2ecf20Sopenharmony_ci * write routines & macros 1698c2ecf20Sopenharmony_ci */ 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci/** 1728c2ecf20Sopenharmony_ci * DVB_RINGBUFFER_WRITE_BYTE - write single byte to ring buffer 1738c2ecf20Sopenharmony_ci * 1748c2ecf20Sopenharmony_ci * @rbuf: pointer to struct dvb_ringbuffer 1758c2ecf20Sopenharmony_ci * @byte: byte to write 1768c2ecf20Sopenharmony_ci */ 1778c2ecf20Sopenharmony_ci#define DVB_RINGBUFFER_WRITE_BYTE(rbuf, byte) \ 1788c2ecf20Sopenharmony_ci { (rbuf)->data[(rbuf)->pwrite] = (byte); \ 1798c2ecf20Sopenharmony_ci (rbuf)->pwrite = ((rbuf)->pwrite + 1) % (rbuf)->size; } 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci/** 1828c2ecf20Sopenharmony_ci * dvb_ringbuffer_write - Writes a buffer into the ringbuffer 1838c2ecf20Sopenharmony_ci * 1848c2ecf20Sopenharmony_ci * @rbuf: pointer to struct dvb_ringbuffer 1858c2ecf20Sopenharmony_ci * @buf: pointer to the buffer where the data will be read 1868c2ecf20Sopenharmony_ci * @len: bytes from ring buffer into @buf 1878c2ecf20Sopenharmony_ci * 1888c2ecf20Sopenharmony_ci * This variant assumes that the buffer is a memory at the Kernel space 1898c2ecf20Sopenharmony_ci * 1908c2ecf20Sopenharmony_ci * return: number of bytes transferred or -EFAULT 1918c2ecf20Sopenharmony_ci */ 1928c2ecf20Sopenharmony_ciextern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, 1938c2ecf20Sopenharmony_ci size_t len); 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci/** 1968c2ecf20Sopenharmony_ci * dvb_ringbuffer_write_user - Writes a buffer received via a user pointer 1978c2ecf20Sopenharmony_ci * 1988c2ecf20Sopenharmony_ci * @rbuf: pointer to struct dvb_ringbuffer 1998c2ecf20Sopenharmony_ci * @buf: pointer to the buffer where the data will be read 2008c2ecf20Sopenharmony_ci * @len: bytes from ring buffer into @buf 2018c2ecf20Sopenharmony_ci * 2028c2ecf20Sopenharmony_ci * This variant assumes that the buffer is a memory at the userspace. So, 2038c2ecf20Sopenharmony_ci * it will internally call copy_from_user(). 2048c2ecf20Sopenharmony_ci * 2058c2ecf20Sopenharmony_ci * Return: number of bytes transferred or -EFAULT 2068c2ecf20Sopenharmony_ci */ 2078c2ecf20Sopenharmony_ciextern ssize_t dvb_ringbuffer_write_user(struct dvb_ringbuffer *rbuf, 2088c2ecf20Sopenharmony_ci const u8 __user *buf, size_t len); 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci/** 2118c2ecf20Sopenharmony_ci * dvb_ringbuffer_pkt_write - Write a packet into the ringbuffer. 2128c2ecf20Sopenharmony_ci * 2138c2ecf20Sopenharmony_ci * @rbuf: Ringbuffer to write to. 2148c2ecf20Sopenharmony_ci * @buf: Buffer to write. 2158c2ecf20Sopenharmony_ci * @len: Length of buffer (currently limited to 65535 bytes max). 2168c2ecf20Sopenharmony_ci * 2178c2ecf20Sopenharmony_ci * Return: Number of bytes written, or -EFAULT, -ENOMEM, -EVINAL. 2188c2ecf20Sopenharmony_ci */ 2198c2ecf20Sopenharmony_ciextern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8 *buf, 2208c2ecf20Sopenharmony_ci size_t len); 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci/** 2238c2ecf20Sopenharmony_ci * dvb_ringbuffer_pkt_read_user - Read from a packet in the ringbuffer. 2248c2ecf20Sopenharmony_ci * 2258c2ecf20Sopenharmony_ci * @rbuf: Ringbuffer concerned. 2268c2ecf20Sopenharmony_ci * @idx: Packet index as returned by dvb_ringbuffer_pkt_next(). 2278c2ecf20Sopenharmony_ci * @offset: Offset into packet to read from. 2288c2ecf20Sopenharmony_ci * @buf: Destination buffer for data. 2298c2ecf20Sopenharmony_ci * @len: Size of destination buffer. 2308c2ecf20Sopenharmony_ci * 2318c2ecf20Sopenharmony_ci * Return: Number of bytes read, or -EFAULT. 2328c2ecf20Sopenharmony_ci * 2338c2ecf20Sopenharmony_ci * .. note:: 2348c2ecf20Sopenharmony_ci * 2358c2ecf20Sopenharmony_ci * unlike dvb_ringbuffer_read(), this does **NOT** update the read pointer 2368c2ecf20Sopenharmony_ci * in the ringbuffer. You must use dvb_ringbuffer_pkt_dispose() to mark a 2378c2ecf20Sopenharmony_ci * packet as no longer required. 2388c2ecf20Sopenharmony_ci */ 2398c2ecf20Sopenharmony_ciextern ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, 2408c2ecf20Sopenharmony_ci size_t idx, 2418c2ecf20Sopenharmony_ci int offset, u8 __user *buf, 2428c2ecf20Sopenharmony_ci size_t len); 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci/** 2458c2ecf20Sopenharmony_ci * dvb_ringbuffer_pkt_read - Read from a packet in the ringbuffer. 2468c2ecf20Sopenharmony_ci * Note: unlike dvb_ringbuffer_read_user(), this DOES update the read pointer 2478c2ecf20Sopenharmony_ci * in the ringbuffer. 2488c2ecf20Sopenharmony_ci * 2498c2ecf20Sopenharmony_ci * @rbuf: Ringbuffer concerned. 2508c2ecf20Sopenharmony_ci * @idx: Packet index as returned by dvb_ringbuffer_pkt_next(). 2518c2ecf20Sopenharmony_ci * @offset: Offset into packet to read from. 2528c2ecf20Sopenharmony_ci * @buf: Destination buffer for data. 2538c2ecf20Sopenharmony_ci * @len: Size of destination buffer. 2548c2ecf20Sopenharmony_ci * 2558c2ecf20Sopenharmony_ci * Return: Number of bytes read, or -EFAULT. 2568c2ecf20Sopenharmony_ci */ 2578c2ecf20Sopenharmony_ciextern ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx, 2588c2ecf20Sopenharmony_ci int offset, u8 *buf, size_t len); 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci/** 2618c2ecf20Sopenharmony_ci * dvb_ringbuffer_pkt_dispose - Dispose of a packet in the ring buffer. 2628c2ecf20Sopenharmony_ci * 2638c2ecf20Sopenharmony_ci * @rbuf: Ring buffer concerned. 2648c2ecf20Sopenharmony_ci * @idx: Packet index as returned by dvb_ringbuffer_pkt_next(). 2658c2ecf20Sopenharmony_ci */ 2668c2ecf20Sopenharmony_ciextern void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx); 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci/** 2698c2ecf20Sopenharmony_ci * dvb_ringbuffer_pkt_next - Get the index of the next packet in a ringbuffer. 2708c2ecf20Sopenharmony_ci * 2718c2ecf20Sopenharmony_ci * @rbuf: Ringbuffer concerned. 2728c2ecf20Sopenharmony_ci * @idx: Previous packet index, or -1 to return the first packet index. 2738c2ecf20Sopenharmony_ci * @pktlen: On success, will be updated to contain the length of the packet 2748c2ecf20Sopenharmony_ci * in bytes. 2758c2ecf20Sopenharmony_ci * returns Packet index (if >=0), or -1 if no packets available. 2768c2ecf20Sopenharmony_ci */ 2778c2ecf20Sopenharmony_ciextern ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, 2788c2ecf20Sopenharmony_ci size_t idx, size_t *pktlen); 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci#endif /* _DVB_RINGBUFFER_H_ */ 281