1 /* 2 * ngene-dvb.c: nGene PCIe bridge driver - DVB functions 3 * 4 * Copyright (C) 2005-2007 Micronas 5 * 6 * Copyright (C) 2008-2009 Ralph Metzler <rjkm@metzlerbros.de> 7 * Modifications for new nGene firmware, 8 * support for EEPROM-copying, 9 * support for new dual DVB-S2 card prototype 10 * 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * version 2 only, as published by the Free Software Foundation. 15 * 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 General Public License for more details. 21 * 22 * To obtain the license, point your browser to 23 * http://www.gnu.org/copyleft/gpl.html 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 static int ci_tsfix = 1; 42 module_param(ci_tsfix, int, 0444); 43 MODULE_PARM_DESC(ci_tsfix, "Detect and fix TS buffer offset shifts in conjunction with CI expansions (default: 1/enabled)"); 44 45 /****************************************************************************/ 46 /* COMMAND API interface ****************************************************/ 47 /****************************************************************************/ 48 49 static ssize_t ts_write(struct file *file, const char __user *buf, 50 size_t count, loff_t *ppos) 51 { 52 struct dvb_device *dvbdev = file->private_data; 53 struct ngene_channel *chan = dvbdev->priv; 54 struct ngene *dev = chan->dev; 55 56 if (wait_event_interruptible(dev->tsout_rbuf.queue, 57 dvb_ringbuffer_free 58 (&dev->tsout_rbuf) >= count) < 0) 59 return 0; 60 61 dvb_ringbuffer_write_user(&dev->tsout_rbuf, buf, count); 62 63 return count; 64 } 65 66 static ssize_t ts_read(struct file *file, char __user *buf, 67 size_t count, loff_t *ppos) 68 { 69 struct dvb_device *dvbdev = file->private_data; 70 struct ngene_channel *chan = dvbdev->priv; 71 struct ngene *dev = chan->dev; 72 int left, avail; 73 74 left = count; 75 while (left) { 76 if (wait_event_interruptible( 77 dev->tsin_rbuf.queue, 78 dvb_ringbuffer_avail(&dev->tsin_rbuf) > 0) < 0) 79 return -EAGAIN; 80 avail = dvb_ringbuffer_avail(&dev->tsin_rbuf); 81 if (avail > left) 82 avail = left; 83 dvb_ringbuffer_read_user(&dev->tsin_rbuf, buf, avail); 84 left -= avail; 85 buf += avail; 86 } 87 return count; 88 } 89 90 static __poll_t ts_poll(struct file *file, poll_table *wait) 91 { 92 struct dvb_device *dvbdev = file->private_data; 93 struct ngene_channel *chan = dvbdev->priv; 94 struct ngene *dev = chan->dev; 95 struct dvb_ringbuffer *rbuf = &dev->tsin_rbuf; 96 struct dvb_ringbuffer *wbuf = &dev->tsout_rbuf; 97 __poll_t mask = 0; 98 99 poll_wait(file, &rbuf->queue, wait); 100 poll_wait(file, &wbuf->queue, wait); 101 102 if (!dvb_ringbuffer_empty(rbuf)) 103 mask |= EPOLLIN | EPOLLRDNORM; 104 if (dvb_ringbuffer_free(wbuf) >= 188) 105 mask |= EPOLLOUT | EPOLLWRNORM; 106 107 return mask; 108 } 109 110 static const struct file_operations ci_fops = { 111 .owner = THIS_MODULE, 112 .read = ts_read, 113 .write = ts_write, 114 .open = dvb_generic_open, 115 .release = dvb_generic_release, 116 .poll = ts_poll, 117 .mmap = NULL, 118 }; 119 120 struct dvb_device ngene_dvbdev_ci = { 121 .priv = NULL, 122 .readers = 1, 123 .writers = 1, 124 .users = 2, 125 .fops = &ci_fops, 126 }; 127 128 129 /****************************************************************************/ 130 /* DVB functions and API interface ******************************************/ 131 /****************************************************************************/ 132 133 static void swap_buffer(u32 *p, u32 len) 134 { 135 while (len) { 136 *p = swab32(*p); 137 p++; 138 len -= 4; 139 } 140 } 141 142 /* start of filler packet */ 143 static u8 fill_ts[] = { 0x47, 0x1f, 0xff, 0x10, TS_FILLER }; 144 145 static int tsin_find_offset(void *buf, u32 len) 146 { 147 int i, l; 148 149 l = len - sizeof(fill_ts); 150 if (l <= 0) 151 return -1; 152 153 for (i = 0; i < l; i++) { 154 if (((char *)buf)[i] == 0x47) { 155 if (!memcmp(buf + i, fill_ts, sizeof(fill_ts))) 156 return i % 188; 157 } 158 } 159 160 return -1; 161 } 162 163 static inline void tsin_copy_stripped(struct ngene *dev, void *buf) 164 { 165 if (memcmp(buf, fill_ts, sizeof(fill_ts)) != 0) { 166 if (dvb_ringbuffer_free(&dev->tsin_rbuf) >= 188) { 167 dvb_ringbuffer_write(&dev->tsin_rbuf, buf, 188); 168 wake_up(&dev->tsin_rbuf.queue); 169 } 170 } 171 } 172 173 void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) 174 { 175 struct ngene_channel *chan = priv; 176 struct ngene *dev = chan->dev; 177 int tsoff; 178 179 if (flags & DF_SWAP32) 180 swap_buffer(buf, len); 181 182 if (dev->ci.en && chan->number == 2) { 183 /* blindly copy buffers if ci_tsfix is disabled */ 184 if (!ci_tsfix) { 185 while (len >= 188) { 186 tsin_copy_stripped(dev, buf); 187 188 buf += 188; 189 len -= 188; 190 } 191 return NULL; 192 } 193 194 /* ci_tsfix = 1 */ 195 196 /* 197 * since the remainder of the TS packet which got cut off 198 * in the previous tsin_exchange() run is at the beginning 199 * of the new TS buffer, append this to the temp buffer and 200 * send it to the DVB ringbuffer afterwards. 201 */ 202 if (chan->tsin_offset) { 203 memcpy(&chan->tsin_buffer[(188 - chan->tsin_offset)], 204 buf, chan->tsin_offset); 205 tsin_copy_stripped(dev, &chan->tsin_buffer); 206 207 buf += chan->tsin_offset; 208 len -= chan->tsin_offset; 209 } 210 211 /* 212 * copy TS packets to the DVB ringbuffer and detect new offset 213 * shifts by checking for a valid TS SYNC byte 214 */ 215 while (len >= 188) { 216 if (*((char *)buf) != 0x47) { 217 /* 218 * no SYNC header, find new offset shift 219 * (max. 188 bytes, tsoff will be mod 188) 220 */ 221 tsoff = tsin_find_offset(buf, len); 222 if (tsoff > 0) { 223 chan->tsin_offset += tsoff; 224 chan->tsin_offset %= 188; 225 226 buf += tsoff; 227 len -= tsoff; 228 229 dev_info(&dev->pci_dev->dev, 230 "%s(): tsin_offset shift by %d on channel %d\n", 231 __func__, tsoff, 232 chan->number); 233 234 /* 235 * offset corrected. re-check remaining 236 * len for a full TS frame, break and 237 * skip to fragment handling if < 188. 238 */ 239 if (len < 188) 240 break; 241 } 242 } 243 244 tsin_copy_stripped(dev, buf); 245 246 buf += 188; 247 len -= 188; 248 } 249 250 /* 251 * if a fragment is left, copy to temp buffer. The remainder 252 * will be appended in the next tsin_exchange() iteration. 253 */ 254 if (len > 0 && len < 188) 255 memcpy(&chan->tsin_buffer, buf, len); 256 257 return NULL; 258 } 259 260 if (chan->users > 0) 261 dvb_dmx_swfilter(&chan->demux, buf, len); 262 263 return NULL; 264 } 265 266 void *tsout_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) 267 { 268 struct ngene_channel *chan = priv; 269 struct ngene *dev = chan->dev; 270 u32 alen; 271 272 alen = dvb_ringbuffer_avail(&dev->tsout_rbuf); 273 alen -= alen % 188; 274 275 if (alen < len) 276 FillTSBuffer(buf + alen, len - alen, flags); 277 else 278 alen = len; 279 dvb_ringbuffer_read(&dev->tsout_rbuf, buf, alen); 280 if (flags & DF_SWAP32) 281 swap_buffer((u32 *)buf, alen); 282 wake_up_interruptible(&dev->tsout_rbuf.queue); 283 return buf; 284 } 285 286 287 288 int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed) 289 { 290 struct dvb_demux *dvbdmx = dvbdmxfeed->demux; 291 struct ngene_channel *chan = dvbdmx->priv; 292 293 if (chan->users == 0) { 294 if (!chan->dev->cmd_timeout_workaround || !chan->running) 295 set_transfer(chan, 1); 296 } 297 298 return ++chan->users; 299 } 300 301 int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed) 302 { 303 struct dvb_demux *dvbdmx = dvbdmxfeed->demux; 304 struct ngene_channel *chan = dvbdmx->priv; 305 306 if (--chan->users) 307 return chan->users; 308 309 if (!chan->dev->cmd_timeout_workaround) 310 set_transfer(chan, 0); 311 312 return 0; 313 } 314 315 int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id, 316 int (*start_feed)(struct dvb_demux_feed *), 317 int (*stop_feed)(struct dvb_demux_feed *), 318 void *priv) 319 { 320 dvbdemux->priv = priv; 321 322 dvbdemux->filternum = 256; 323 dvbdemux->feednum = 256; 324 dvbdemux->start_feed = start_feed; 325 dvbdemux->stop_feed = stop_feed; 326 dvbdemux->write_to_decoder = NULL; 327 dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | 328 DMX_SECTION_FILTERING | 329 DMX_MEMORY_BASED_FILTERING); 330 return dvb_dmx_init(dvbdemux); 331 } 332 333 int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev, 334 struct dvb_demux *dvbdemux, 335 struct dmx_frontend *hw_frontend, 336 struct dmx_frontend *mem_frontend, 337 struct dvb_adapter *dvb_adapter) 338 { 339 int ret; 340 341 dmxdev->filternum = 256; 342 dmxdev->demux = &dvbdemux->dmx; 343 dmxdev->capabilities = 0; 344 ret = dvb_dmxdev_init(dmxdev, dvb_adapter); 345 if (ret < 0) 346 return ret; 347 348 hw_frontend->source = DMX_FRONTEND_0; 349 dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend); 350 mem_frontend->source = DMX_MEMORY_FE; 351 dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend); 352 return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend); 353 } 354