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