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