diff options
Diffstat (limited to 'drivers/media/dvb/dvb-core/dvb_ringbuffer.h')
-rw-r--r-- | drivers/media/dvb/dvb-core/dvb_ringbuffer.h | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h new file mode 100644 index 00000000000..41f04dae69b --- /dev/null +++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h | |||
@@ -0,0 +1,186 @@ | |||
1 | /* | ||
2 | * | ||
3 | * dvb_ringbuffer.h: ring buffer implementation for the dvb driver | ||
4 | * | ||
5 | * Copyright (C) 2003 Oliver Endriss | ||
6 | * Copyright (C) 2004 Andrew de Quincey | ||
7 | * | ||
8 | * based on code originally found in av7110.c & dvb_ci.c: | ||
9 | * Copyright (C) 1999-2003 Ralph Metzler & Marcus Metzler | ||
10 | * for convergence integrated media GmbH | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU Lesser General Public License | ||
14 | * as published by the Free Software Foundation; either version 2.1 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU Lesser General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU Lesser General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _DVB_RINGBUFFER_H_ | ||
28 | #define _DVB_RINGBUFFER_H_ | ||
29 | |||
30 | #include <linux/spinlock.h> | ||
31 | #include <linux/wait.h> | ||
32 | |||
33 | struct dvb_ringbuffer { | ||
34 | u8 *data; | ||
35 | ssize_t size; | ||
36 | ssize_t pread; | ||
37 | ssize_t pwrite; | ||
38 | int error; | ||
39 | |||
40 | wait_queue_head_t queue; | ||
41 | spinlock_t lock; | ||
42 | }; | ||
43 | |||
44 | #define DVB_RINGBUFFER_PKTHDRSIZE 3 | ||
45 | |||
46 | |||
47 | /* | ||
48 | ** Notes: | ||
49 | ** ------ | ||
50 | ** (1) For performance reasons read and write routines don't check buffer sizes | ||
51 | ** and/or number of bytes free/available. This has to be done before these | ||
52 | ** routines are called. For example: | ||
53 | ** | ||
54 | ** *** write <buflen> bytes *** | ||
55 | ** free = dvb_ringbuffer_free(rbuf); | ||
56 | ** if (free >= buflen) | ||
57 | ** count = dvb_ringbuffer_write(rbuf, buffer, buflen); | ||
58 | ** else | ||
59 | ** ... | ||
60 | ** | ||
61 | ** *** read min. 1000, max. <bufsize> bytes *** | ||
62 | ** avail = dvb_ringbuffer_avail(rbuf); | ||
63 | ** if (avail >= 1000) | ||
64 | ** count = dvb_ringbuffer_read(rbuf, buffer, min(avail, bufsize)); | ||
65 | ** else | ||
66 | ** ... | ||
67 | ** | ||
68 | ** (2) If there is exactly one reader and one writer, there is no need | ||
69 | ** to lock read or write operations. | ||
70 | ** Two or more readers must be locked against each other. | ||
71 | ** Flushing the buffer counts as a read operation. | ||
72 | ** Resetting the buffer counts as a read and write operation. | ||
73 | ** Two or more writers must be locked against each other. | ||
74 | */ | ||
75 | |||
76 | /* initialize ring buffer, lock and queue */ | ||
77 | extern void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, size_t len); | ||
78 | |||
79 | /* test whether buffer is empty */ | ||
80 | extern int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf); | ||
81 | |||
82 | /* return the number of free bytes in the buffer */ | ||
83 | extern ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf); | ||
84 | |||
85 | /* return the number of bytes waiting in the buffer */ | ||
86 | extern ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf); | ||
87 | |||
88 | |||
89 | /* | ||
90 | ** Reset the read and write pointers to zero and flush the buffer | ||
91 | ** This counts as a read and write operation | ||
92 | */ | ||
93 | extern void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf); | ||
94 | |||
95 | |||
96 | /* read routines & macros */ | ||
97 | /* ---------------------- */ | ||
98 | /* flush buffer */ | ||
99 | extern void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf); | ||
100 | |||
101 | /* flush buffer protected by spinlock and wake-up waiting task(s) */ | ||
102 | extern void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf); | ||
103 | |||
104 | /* peek at byte <offs> in the buffer */ | ||
105 | #define DVB_RINGBUFFER_PEEK(rbuf,offs) \ | ||
106 | (rbuf)->data[((rbuf)->pread+(offs))%(rbuf)->size] | ||
107 | |||
108 | /* advance read ptr by <num> bytes */ | ||
109 | #define DVB_RINGBUFFER_SKIP(rbuf,num) \ | ||
110 | (rbuf)->pread=((rbuf)->pread+(num))%(rbuf)->size | ||
111 | |||
112 | /* | ||
113 | ** read <len> bytes from ring buffer into <buf> | ||
114 | ** <usermem> specifies whether <buf> resides in user space | ||
115 | ** returns number of bytes transferred or -EFAULT | ||
116 | */ | ||
117 | extern ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, | ||
118 | u8 __user *buf, size_t len); | ||
119 | extern void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, | ||
120 | u8 *buf, size_t len); | ||
121 | |||
122 | |||
123 | /* write routines & macros */ | ||
124 | /* ----------------------- */ | ||
125 | /* write single byte to ring buffer */ | ||
126 | #define DVB_RINGBUFFER_WRITE_BYTE(rbuf,byte) \ | ||
127 | { (rbuf)->data[(rbuf)->pwrite]=(byte); \ | ||
128 | (rbuf)->pwrite=((rbuf)->pwrite+1)%(rbuf)->size; } | ||
129 | /* | ||
130 | ** write <len> bytes to ring buffer | ||
131 | ** <usermem> specifies whether <buf> resides in user space | ||
132 | ** returns number of bytes transferred or -EFAULT | ||
133 | */ | ||
134 | extern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, | ||
135 | size_t len); | ||
136 | |||
137 | |||
138 | /** | ||
139 | * Write a packet into the ringbuffer. | ||
140 | * | ||
141 | * <rbuf> Ringbuffer to write to. | ||
142 | * <buf> Buffer to write. | ||
143 | * <len> Length of buffer (currently limited to 65535 bytes max). | ||
144 | * returns Number of bytes written, or -EFAULT, -ENOMEM, -EVINAL. | ||
145 | */ | ||
146 | extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, | ||
147 | size_t len); | ||
148 | |||
149 | /** | ||
150 | * Read from a packet in the ringbuffer. Note: unlike dvb_ringbuffer_read(), this | ||
151 | * does NOT update the read pointer in the ringbuffer. You must use | ||
152 | * dvb_ringbuffer_pkt_dispose() to mark a packet as no longer required. | ||
153 | * | ||
154 | * <rbuf> Ringbuffer concerned. | ||
155 | * <idx> Packet index as returned by dvb_ringbuffer_pkt_next(). | ||
156 | * <offset> Offset into packet to read from. | ||
157 | * <buf> Destination buffer for data. | ||
158 | * <len> Size of destination buffer. | ||
159 | * <usermem> Set to 1 if <buf> is in userspace. | ||
160 | * returns Number of bytes read, or -EFAULT. | ||
161 | */ | ||
162 | extern ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, size_t idx, | ||
163 | int offset, u8 __user *buf, size_t len); | ||
164 | extern ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx, | ||
165 | int offset, u8 *buf, size_t len); | ||
166 | |||
167 | /** | ||
168 | * Dispose of a packet in the ring buffer. | ||
169 | * | ||
170 | * <rbuf> Ring buffer concerned. | ||
171 | * <idx> Packet index as returned by dvb_ringbuffer_pkt_next(). | ||
172 | */ | ||
173 | extern void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx); | ||
174 | |||
175 | /** | ||
176 | * Get the index of the next packet in a ringbuffer. | ||
177 | * | ||
178 | * <rbuf> Ringbuffer concerned. | ||
179 | * <idx> Previous packet index, or -1 to return the first packet index. | ||
180 | * <pktlen> On success, will be updated to contain the length of the packet in bytes. | ||
181 | * returns Packet index (if >=0), or -1 if no packets available. | ||
182 | */ | ||
183 | extern ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t* pktlen); | ||
184 | |||
185 | |||
186 | #endif /* _DVB_RINGBUFFER_H_ */ | ||