1fada1935SMauro Carvalho Chehab /* 2fada1935SMauro Carvalho Chehab * 3fada1935SMauro Carvalho Chehab * dvb_ringbuffer.h: ring buffer implementation for the dvb driver 4fada1935SMauro Carvalho Chehab * 5fada1935SMauro Carvalho Chehab * Copyright (C) 2003 Oliver Endriss 6fada1935SMauro Carvalho Chehab * Copyright (C) 2004 Andrew de Quincey 7fada1935SMauro Carvalho Chehab * 8fada1935SMauro Carvalho Chehab * based on code originally found in av7110.c & dvb_ci.c: 9fada1935SMauro Carvalho Chehab * Copyright (C) 1999-2003 Ralph Metzler & Marcus Metzler 10fada1935SMauro Carvalho Chehab * for convergence integrated media GmbH 11fada1935SMauro Carvalho Chehab * 12fada1935SMauro Carvalho Chehab * This program is free software; you can redistribute it and/or 13fada1935SMauro Carvalho Chehab * modify it under the terms of the GNU Lesser General Public License 14fada1935SMauro Carvalho Chehab * as published by the Free Software Foundation; either version 2.1 15fada1935SMauro Carvalho Chehab * of the License, or (at your option) any later version. 16fada1935SMauro Carvalho Chehab * 17fada1935SMauro Carvalho Chehab * This program is distributed in the hope that it will be useful, 18fada1935SMauro Carvalho Chehab * but WITHOUT ANY WARRANTY; without even the implied warranty of 19fada1935SMauro Carvalho Chehab * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20fada1935SMauro Carvalho Chehab * GNU Lesser General Public License for more details. 21fada1935SMauro Carvalho Chehab */ 22fada1935SMauro Carvalho Chehab 23fada1935SMauro Carvalho Chehab #ifndef _DVB_RINGBUFFER_H_ 24fada1935SMauro Carvalho Chehab #define _DVB_RINGBUFFER_H_ 25fada1935SMauro Carvalho Chehab 26fada1935SMauro Carvalho Chehab #include <linux/spinlock.h> 27fada1935SMauro Carvalho Chehab #include <linux/wait.h> 28fada1935SMauro Carvalho Chehab 29fada1935SMauro Carvalho Chehab /** 30fada1935SMauro Carvalho Chehab * struct dvb_ringbuffer - Describes a ring buffer used at DVB framework 31fada1935SMauro Carvalho Chehab * 32fada1935SMauro Carvalho Chehab * @data: Area were the ringbuffer data is written 33fada1935SMauro Carvalho Chehab * @size: size of the ringbuffer 34fada1935SMauro Carvalho Chehab * @pread: next position to read 35fada1935SMauro Carvalho Chehab * @pwrite: next position to write 36fada1935SMauro Carvalho Chehab * @error: used by ringbuffer clients to indicate that an error happened. 37fada1935SMauro Carvalho Chehab * @queue: Wait queue used by ringbuffer clients to indicate when buffer 38fada1935SMauro Carvalho Chehab * was filled 39fada1935SMauro Carvalho Chehab * @lock: Spinlock used to protect the ringbuffer 40fada1935SMauro Carvalho Chehab */ 41fada1935SMauro Carvalho Chehab struct dvb_ringbuffer { 42fada1935SMauro Carvalho Chehab u8 *data; 43fada1935SMauro Carvalho Chehab ssize_t size; 44fada1935SMauro Carvalho Chehab ssize_t pread; 45fada1935SMauro Carvalho Chehab ssize_t pwrite; 46fada1935SMauro Carvalho Chehab int error; 47fada1935SMauro Carvalho Chehab 48fada1935SMauro Carvalho Chehab wait_queue_head_t queue; 49fada1935SMauro Carvalho Chehab spinlock_t lock; 50fada1935SMauro Carvalho Chehab }; 51fada1935SMauro Carvalho Chehab 52fada1935SMauro Carvalho Chehab #define DVB_RINGBUFFER_PKTHDRSIZE 3 53fada1935SMauro Carvalho Chehab 54fada1935SMauro Carvalho Chehab /** 55fada1935SMauro Carvalho Chehab * dvb_ringbuffer_init - initialize ring buffer, lock and queue 56fada1935SMauro Carvalho Chehab * 57fada1935SMauro Carvalho Chehab * @rbuf: pointer to struct dvb_ringbuffer 58fada1935SMauro Carvalho Chehab * @data: pointer to the buffer where the data will be stored 59fada1935SMauro Carvalho Chehab * @len: bytes from ring buffer into @buf 60fada1935SMauro Carvalho Chehab */ 61fada1935SMauro Carvalho Chehab extern void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, 62fada1935SMauro Carvalho Chehab size_t len); 63fada1935SMauro Carvalho Chehab 64fada1935SMauro Carvalho Chehab /** 65fada1935SMauro Carvalho Chehab * dvb_ringbuffer_empty - test whether buffer is empty 66fada1935SMauro Carvalho Chehab * 67fada1935SMauro Carvalho Chehab * @rbuf: pointer to struct dvb_ringbuffer 68fada1935SMauro Carvalho Chehab */ 69fada1935SMauro Carvalho Chehab extern int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf); 70fada1935SMauro Carvalho Chehab 71fada1935SMauro Carvalho Chehab /** 72fada1935SMauro Carvalho Chehab * dvb_ringbuffer_free - returns the number of free bytes in the buffer 73fada1935SMauro Carvalho Chehab * 74fada1935SMauro Carvalho Chehab * @rbuf: pointer to struct dvb_ringbuffer 75fada1935SMauro Carvalho Chehab * 76fada1935SMauro Carvalho Chehab * Return: number of free bytes in the buffer 77fada1935SMauro Carvalho Chehab */ 78fada1935SMauro Carvalho Chehab extern ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf); 79fada1935SMauro Carvalho Chehab 80fada1935SMauro Carvalho Chehab /** 81fada1935SMauro Carvalho Chehab * dvb_ringbuffer_avail - returns the number of bytes waiting in the buffer 82fada1935SMauro Carvalho Chehab * 83fada1935SMauro Carvalho Chehab * @rbuf: pointer to struct dvb_ringbuffer 84fada1935SMauro Carvalho Chehab * 85fada1935SMauro Carvalho Chehab * Return: number of bytes waiting in the buffer 86fada1935SMauro Carvalho Chehab */ 87fada1935SMauro Carvalho Chehab extern ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf); 88fada1935SMauro Carvalho Chehab 89fada1935SMauro Carvalho Chehab /** 90fada1935SMauro Carvalho Chehab * dvb_ringbuffer_reset - resets the ringbuffer to initial state 91fada1935SMauro Carvalho Chehab * 92fada1935SMauro Carvalho Chehab * @rbuf: pointer to struct dvb_ringbuffer 93fada1935SMauro Carvalho Chehab * 94fada1935SMauro Carvalho Chehab * Resets the read and write pointers to zero and flush the buffer. 95fada1935SMauro Carvalho Chehab * 96fada1935SMauro Carvalho Chehab * This counts as a read and write operation 97fada1935SMauro Carvalho Chehab */ 98fada1935SMauro Carvalho Chehab extern void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf); 99fada1935SMauro Carvalho Chehab 100fada1935SMauro Carvalho Chehab /* 101fada1935SMauro Carvalho Chehab * read routines & macros 102fada1935SMauro Carvalho Chehab */ 103fada1935SMauro Carvalho Chehab 104fada1935SMauro Carvalho Chehab /** 105fada1935SMauro Carvalho Chehab * dvb_ringbuffer_flush - flush buffer 106fada1935SMauro Carvalho Chehab * 107fada1935SMauro Carvalho Chehab * @rbuf: pointer to struct dvb_ringbuffer 108fada1935SMauro Carvalho Chehab */ 109fada1935SMauro Carvalho Chehab extern void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf); 110fada1935SMauro Carvalho Chehab 111fada1935SMauro Carvalho Chehab /** 112fada1935SMauro Carvalho Chehab * dvb_ringbuffer_flush_spinlock_wakeup- flush buffer protected by spinlock 113fada1935SMauro Carvalho Chehab * and wake-up waiting task(s) 114fada1935SMauro Carvalho Chehab * 115fada1935SMauro Carvalho Chehab * @rbuf: pointer to struct dvb_ringbuffer 116fada1935SMauro Carvalho Chehab */ 117fada1935SMauro Carvalho Chehab extern void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf); 118fada1935SMauro Carvalho Chehab 119fada1935SMauro Carvalho Chehab /** 120fada1935SMauro Carvalho Chehab * DVB_RINGBUFFER_PEEK - peek at byte @offs in the buffer 121fada1935SMauro Carvalho Chehab * 122fada1935SMauro Carvalho Chehab * @rbuf: pointer to struct dvb_ringbuffer 123fada1935SMauro Carvalho Chehab * @offs: offset inside the ringbuffer 124fada1935SMauro Carvalho Chehab */ 125fada1935SMauro Carvalho Chehab #define DVB_RINGBUFFER_PEEK(rbuf, offs) \ 126fada1935SMauro Carvalho Chehab ((rbuf)->data[((rbuf)->pread + (offs)) % (rbuf)->size]) 127fada1935SMauro Carvalho Chehab 128fada1935SMauro Carvalho Chehab /** 129fada1935SMauro Carvalho Chehab * DVB_RINGBUFFER_SKIP - advance read ptr by @num bytes 130fada1935SMauro Carvalho Chehab * 131fada1935SMauro Carvalho Chehab * @rbuf: pointer to struct dvb_ringbuffer 132fada1935SMauro Carvalho Chehab * @num: number of bytes to advance 133fada1935SMauro Carvalho Chehab */ 134fada1935SMauro Carvalho Chehab #define DVB_RINGBUFFER_SKIP(rbuf, num) {\ 135fada1935SMauro Carvalho Chehab (rbuf)->pread = ((rbuf)->pread + (num)) % (rbuf)->size;\ 136fada1935SMauro Carvalho Chehab } 137fada1935SMauro Carvalho Chehab 138fada1935SMauro Carvalho Chehab /** 139fada1935SMauro Carvalho Chehab * dvb_ringbuffer_read_user - Reads a buffer into a user pointer 140fada1935SMauro Carvalho Chehab * 141fada1935SMauro Carvalho Chehab * @rbuf: pointer to struct dvb_ringbuffer 142fada1935SMauro Carvalho Chehab * @buf: pointer to the buffer where the data will be stored 143fada1935SMauro Carvalho Chehab * @len: bytes from ring buffer into @buf 144fada1935SMauro Carvalho Chehab * 145fada1935SMauro Carvalho Chehab * This variant assumes that the buffer is a memory at the userspace. So, 146fada1935SMauro Carvalho Chehab * it will internally call copy_to_user(). 147fada1935SMauro Carvalho Chehab * 148fada1935SMauro Carvalho Chehab * Return: number of bytes transferred or -EFAULT 149fada1935SMauro Carvalho Chehab */ 150fada1935SMauro Carvalho Chehab extern ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, 151fada1935SMauro Carvalho Chehab u8 __user *buf, size_t len); 152fada1935SMauro Carvalho Chehab 153fada1935SMauro Carvalho Chehab /** 154fada1935SMauro Carvalho Chehab * dvb_ringbuffer_read - Reads a buffer into a pointer 155fada1935SMauro Carvalho Chehab * 156fada1935SMauro Carvalho Chehab * @rbuf: pointer to struct dvb_ringbuffer 157fada1935SMauro Carvalho Chehab * @buf: pointer to the buffer where the data will be stored 158fada1935SMauro Carvalho Chehab * @len: bytes from ring buffer into @buf 159fada1935SMauro Carvalho Chehab * 160fada1935SMauro Carvalho Chehab * This variant assumes that the buffer is a memory at the Kernel space 161fada1935SMauro Carvalho Chehab * 162fada1935SMauro Carvalho Chehab * Return: number of bytes transferred or -EFAULT 163fada1935SMauro Carvalho Chehab */ 164fada1935SMauro Carvalho Chehab extern void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, 165fada1935SMauro Carvalho Chehab u8 *buf, size_t len); 166fada1935SMauro Carvalho Chehab 167fada1935SMauro Carvalho Chehab /* 168fada1935SMauro Carvalho Chehab * write routines & macros 169fada1935SMauro Carvalho Chehab */ 170fada1935SMauro Carvalho Chehab 171fada1935SMauro Carvalho Chehab /** 172fada1935SMauro Carvalho Chehab * DVB_RINGBUFFER_WRITE_BYTE - write single byte to ring buffer 173fada1935SMauro Carvalho Chehab * 174fada1935SMauro Carvalho Chehab * @rbuf: pointer to struct dvb_ringbuffer 175fada1935SMauro Carvalho Chehab * @byte: byte to write 176fada1935SMauro Carvalho Chehab */ 177fada1935SMauro Carvalho Chehab #define DVB_RINGBUFFER_WRITE_BYTE(rbuf, byte) \ 178fada1935SMauro Carvalho Chehab { (rbuf)->data[(rbuf)->pwrite] = (byte); \ 179fada1935SMauro Carvalho Chehab (rbuf)->pwrite = ((rbuf)->pwrite + 1) % (rbuf)->size; } 180fada1935SMauro Carvalho Chehab 181fada1935SMauro Carvalho Chehab /** 182fada1935SMauro Carvalho Chehab * dvb_ringbuffer_write - Writes a buffer into the ringbuffer 183fada1935SMauro Carvalho Chehab * 184fada1935SMauro Carvalho Chehab * @rbuf: pointer to struct dvb_ringbuffer 185fada1935SMauro Carvalho Chehab * @buf: pointer to the buffer where the data will be read 186fada1935SMauro Carvalho Chehab * @len: bytes from ring buffer into @buf 187fada1935SMauro Carvalho Chehab * 188fada1935SMauro Carvalho Chehab * This variant assumes that the buffer is a memory at the Kernel space 189fada1935SMauro Carvalho Chehab * 190fada1935SMauro Carvalho Chehab * return: number of bytes transferred or -EFAULT 191fada1935SMauro Carvalho Chehab */ 192fada1935SMauro Carvalho Chehab extern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, 193fada1935SMauro Carvalho Chehab size_t len); 194fada1935SMauro Carvalho Chehab 195fada1935SMauro Carvalho Chehab /** 196fada1935SMauro Carvalho Chehab * dvb_ringbuffer_write_user - Writes a buffer received via a user pointer 197fada1935SMauro Carvalho Chehab * 198fada1935SMauro Carvalho Chehab * @rbuf: pointer to struct dvb_ringbuffer 199fada1935SMauro Carvalho Chehab * @buf: pointer to the buffer where the data will be read 200fada1935SMauro Carvalho Chehab * @len: bytes from ring buffer into @buf 201fada1935SMauro Carvalho Chehab * 202fada1935SMauro Carvalho Chehab * This variant assumes that the buffer is a memory at the userspace. So, 203fada1935SMauro Carvalho Chehab * it will internally call copy_from_user(). 204fada1935SMauro Carvalho Chehab * 205fada1935SMauro Carvalho Chehab * Return: number of bytes transferred or -EFAULT 206fada1935SMauro Carvalho Chehab */ 207fada1935SMauro Carvalho Chehab extern ssize_t dvb_ringbuffer_write_user(struct dvb_ringbuffer *rbuf, 208fada1935SMauro Carvalho Chehab const u8 __user *buf, size_t len); 209fada1935SMauro Carvalho Chehab 210fada1935SMauro Carvalho Chehab /** 211fada1935SMauro Carvalho Chehab * dvb_ringbuffer_pkt_write - Write a packet into the ringbuffer. 212fada1935SMauro Carvalho Chehab * 213fada1935SMauro Carvalho Chehab * @rbuf: Ringbuffer to write to. 214fada1935SMauro Carvalho Chehab * @buf: Buffer to write. 215fada1935SMauro Carvalho Chehab * @len: Length of buffer (currently limited to 65535 bytes max). 216fada1935SMauro Carvalho Chehab * 217*b5411dd4SGeert Uytterhoeven * Return: Number of bytes written, or -EFAULT, -ENOMEM, -EINVAL. 218fada1935SMauro Carvalho Chehab */ 219fada1935SMauro Carvalho Chehab extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8 *buf, 220fada1935SMauro Carvalho Chehab size_t len); 221fada1935SMauro Carvalho Chehab 222fada1935SMauro Carvalho Chehab /** 223fada1935SMauro Carvalho Chehab * dvb_ringbuffer_pkt_read_user - Read from a packet in the ringbuffer. 224fada1935SMauro Carvalho Chehab * 225fada1935SMauro Carvalho Chehab * @rbuf: Ringbuffer concerned. 226fada1935SMauro Carvalho Chehab * @idx: Packet index as returned by dvb_ringbuffer_pkt_next(). 227fada1935SMauro Carvalho Chehab * @offset: Offset into packet to read from. 228fada1935SMauro Carvalho Chehab * @buf: Destination buffer for data. 229fada1935SMauro Carvalho Chehab * @len: Size of destination buffer. 230fada1935SMauro Carvalho Chehab * 231fada1935SMauro Carvalho Chehab * Return: Number of bytes read, or -EFAULT. 232fada1935SMauro Carvalho Chehab * 233fada1935SMauro Carvalho Chehab * .. note:: 234fada1935SMauro Carvalho Chehab * 235fada1935SMauro Carvalho Chehab * unlike dvb_ringbuffer_read(), this does **NOT** update the read pointer 236fada1935SMauro Carvalho Chehab * in the ringbuffer. You must use dvb_ringbuffer_pkt_dispose() to mark a 237fada1935SMauro Carvalho Chehab * packet as no longer required. 238fada1935SMauro Carvalho Chehab */ 239fada1935SMauro Carvalho Chehab extern ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, 240fada1935SMauro Carvalho Chehab size_t idx, 241fada1935SMauro Carvalho Chehab int offset, u8 __user *buf, 242fada1935SMauro Carvalho Chehab size_t len); 243fada1935SMauro Carvalho Chehab 244fada1935SMauro Carvalho Chehab /** 245fada1935SMauro Carvalho Chehab * dvb_ringbuffer_pkt_read - Read from a packet in the ringbuffer. 246fada1935SMauro Carvalho Chehab * Note: unlike dvb_ringbuffer_read_user(), this DOES update the read pointer 247fada1935SMauro Carvalho Chehab * in the ringbuffer. 248fada1935SMauro Carvalho Chehab * 249fada1935SMauro Carvalho Chehab * @rbuf: Ringbuffer concerned. 250fada1935SMauro Carvalho Chehab * @idx: Packet index as returned by dvb_ringbuffer_pkt_next(). 251fada1935SMauro Carvalho Chehab * @offset: Offset into packet to read from. 252fada1935SMauro Carvalho Chehab * @buf: Destination buffer for data. 253fada1935SMauro Carvalho Chehab * @len: Size of destination buffer. 254fada1935SMauro Carvalho Chehab * 255fada1935SMauro Carvalho Chehab * Return: Number of bytes read, or -EFAULT. 256fada1935SMauro Carvalho Chehab */ 257fada1935SMauro Carvalho Chehab extern ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx, 258fada1935SMauro Carvalho Chehab int offset, u8 *buf, size_t len); 259fada1935SMauro Carvalho Chehab 260fada1935SMauro Carvalho Chehab /** 261fada1935SMauro Carvalho Chehab * dvb_ringbuffer_pkt_dispose - Dispose of a packet in the ring buffer. 262fada1935SMauro Carvalho Chehab * 263fada1935SMauro Carvalho Chehab * @rbuf: Ring buffer concerned. 264fada1935SMauro Carvalho Chehab * @idx: Packet index as returned by dvb_ringbuffer_pkt_next(). 265fada1935SMauro Carvalho Chehab */ 266fada1935SMauro Carvalho Chehab extern void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx); 267fada1935SMauro Carvalho Chehab 268fada1935SMauro Carvalho Chehab /** 269fada1935SMauro Carvalho Chehab * dvb_ringbuffer_pkt_next - Get the index of the next packet in a ringbuffer. 270fada1935SMauro Carvalho Chehab * 271fada1935SMauro Carvalho Chehab * @rbuf: Ringbuffer concerned. 272fada1935SMauro Carvalho Chehab * @idx: Previous packet index, or -1 to return the first packet index. 273fada1935SMauro Carvalho Chehab * @pktlen: On success, will be updated to contain the length of the packet 274fada1935SMauro Carvalho Chehab * in bytes. 275fada1935SMauro Carvalho Chehab * returns Packet index (if >=0), or -1 if no packets available. 276fada1935SMauro Carvalho Chehab */ 277fada1935SMauro Carvalho Chehab extern ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, 278fada1935SMauro Carvalho Chehab size_t idx, size_t *pktlen); 279fada1935SMauro Carvalho Chehab 280fada1935SMauro Carvalho Chehab #endif /* _DVB_RINGBUFFER_H_ */ 281