1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include <linux/module.h>
27#include <linux/init.h>
28#include <linux/delay.h>
29#include <linux/slab.h>
30#include <linux/poll.h>
31#include <linux/io.h>
32#include <asm/div64.h>
33#include <linux/pci.h>
34#include <linux/timer.h>
35#include <linux/byteorder/generic.h>
36#include <linux/firmware.h>
37#include <linux/vmalloc.h>
38
39#include "ngene.h"
40
41
42
43
44
45
46static ssize_t ts_write(struct file *file, const char __user *buf,
47 size_t count, loff_t *ppos)
48{
49 struct dvb_device *dvbdev = file->private_data;
50 struct ngene_channel *chan = dvbdev->priv;
51 struct ngene *dev = chan->dev;
52
53 if (wait_event_interruptible(dev->tsout_rbuf.queue,
54 dvb_ringbuffer_free
55 (&dev->tsout_rbuf) >= count) < 0)
56 return 0;
57
58 dvb_ringbuffer_write_user(&dev->tsout_rbuf, buf, count);
59
60 return count;
61}
62
63static ssize_t ts_read(struct file *file, char __user *buf,
64 size_t count, loff_t *ppos)
65{
66 struct dvb_device *dvbdev = file->private_data;
67 struct ngene_channel *chan = dvbdev->priv;
68 struct ngene *dev = chan->dev;
69 int left, avail;
70
71 left = count;
72 while (left) {
73 if (wait_event_interruptible(
74 dev->tsin_rbuf.queue,
75 dvb_ringbuffer_avail(&dev->tsin_rbuf) > 0) < 0)
76 return -EAGAIN;
77 avail = dvb_ringbuffer_avail(&dev->tsin_rbuf);
78 if (avail > left)
79 avail = left;
80 dvb_ringbuffer_read_user(&dev->tsin_rbuf, buf, avail);
81 left -= avail;
82 buf += avail;
83 }
84 return count;
85}
86
87static const struct file_operations ci_fops = {
88 .owner = THIS_MODULE,
89 .read = ts_read,
90 .write = ts_write,
91 .open = dvb_generic_open,
92 .release = dvb_generic_release,
93};
94
95struct dvb_device ngene_dvbdev_ci = {
96 .readers = -1,
97 .writers = -1,
98 .users = -1,
99 .fops = &ci_fops,
100};
101
102
103
104
105
106
107static void swap_buffer(u32 *p, u32 len)
108{
109 while (len) {
110 *p = swab32(*p);
111 p++;
112 len -= 4;
113 }
114}
115
116
117static u8 fill_ts[] = { 0x47, 0x1f, 0xff, 0x10, TS_FILLER };
118
119
120#ifdef DEBUG_CI_XFER
121static u32 ok;
122static u32 overflow;
123static u32 stripped;
124#endif
125
126void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
127{
128 struct ngene_channel *chan = priv;
129 struct ngene *dev = chan->dev;
130
131
132 if (flags & DF_SWAP32)
133 swap_buffer(buf, len);
134
135 if (dev->ci.en && chan->number == 2) {
136 while (len >= 188) {
137 if (memcmp(buf, fill_ts, sizeof fill_ts) != 0) {
138 if (dvb_ringbuffer_free(&dev->tsin_rbuf) >= 188) {
139 dvb_ringbuffer_write(&dev->tsin_rbuf, buf, 188);
140 wake_up(&dev->tsin_rbuf.queue);
141#ifdef DEBUG_CI_XFER
142 ok++;
143#endif
144 }
145#ifdef DEBUG_CI_XFER
146 else
147 overflow++;
148#endif
149 }
150#ifdef DEBUG_CI_XFER
151 else
152 stripped++;
153
154 if (ok % 100 == 0 && overflow)
155 printk(KERN_WARNING "%s: ok %u overflow %u dropped %u\n", __func__, ok, overflow, stripped);
156#endif
157 buf += 188;
158 len -= 188;
159 }
160 return NULL;
161 }
162
163 if (chan->users > 0)
164 dvb_dmx_swfilter(&chan->demux, buf, len);
165
166 return NULL;
167}
168
169void *tsout_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
170{
171 struct ngene_channel *chan = priv;
172 struct ngene *dev = chan->dev;
173 u32 alen;
174
175 alen = dvb_ringbuffer_avail(&dev->tsout_rbuf);
176 alen -= alen % 188;
177
178 if (alen < len)
179 FillTSBuffer(buf + alen, len - alen, flags);
180 else
181 alen = len;
182 dvb_ringbuffer_read(&dev->tsout_rbuf, buf, alen);
183 if (flags & DF_SWAP32)
184 swap_buffer((u32 *)buf, alen);
185 wake_up_interruptible(&dev->tsout_rbuf.queue);
186 return buf;
187}
188
189
190
191int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed)
192{
193 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
194 struct ngene_channel *chan = dvbdmx->priv;
195
196 if (chan->users == 0) {
197 if (!chan->dev->cmd_timeout_workaround || !chan->running)
198 set_transfer(chan, 1);
199 }
200
201 return ++chan->users;
202}
203
204int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
205{
206 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
207 struct ngene_channel *chan = dvbdmx->priv;
208
209 if (--chan->users)
210 return chan->users;
211
212 if (!chan->dev->cmd_timeout_workaround)
213 set_transfer(chan, 0);
214
215 return 0;
216}
217
218int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id,
219 int (*start_feed)(struct dvb_demux_feed *),
220 int (*stop_feed)(struct dvb_demux_feed *),
221 void *priv)
222{
223 dvbdemux->priv = priv;
224
225 dvbdemux->filternum = 256;
226 dvbdemux->feednum = 256;
227 dvbdemux->start_feed = start_feed;
228 dvbdemux->stop_feed = stop_feed;
229 dvbdemux->write_to_decoder = NULL;
230 dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
231 DMX_SECTION_FILTERING |
232 DMX_MEMORY_BASED_FILTERING);
233 return dvb_dmx_init(dvbdemux);
234}
235
236int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev,
237 struct dvb_demux *dvbdemux,
238 struct dmx_frontend *hw_frontend,
239 struct dmx_frontend *mem_frontend,
240 struct dvb_adapter *dvb_adapter)
241{
242 int ret;
243
244 dmxdev->filternum = 256;
245 dmxdev->demux = &dvbdemux->dmx;
246 dmxdev->capabilities = 0;
247 ret = dvb_dmxdev_init(dmxdev, dvb_adapter);
248 if (ret < 0)
249 return ret;
250
251 hw_frontend->source = DMX_FRONTEND_0;
252 dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend);
253 mem_frontend->source = DMX_MEMORY_FE;
254 dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend);
255 return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend);
256}
257