2 * FireDTV driver (formerly known as FireSAT)
4 * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
5 * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
13 #include <linux/errno.h>
14 #include <linux/kernel.h>
15 #include <linux/mutex.h>
16 #include <linux/types.h>
18 #include <dvb_demux.h>
19 #include <dvb_frontend.h>
24 #include "firesat-ci.h"
26 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
28 static struct firesat_channel *firesat_channel_allocate(struct firesat *firesat)
30 struct firesat_channel *c = NULL;
33 if (mutex_lock_interruptible(&firesat->demux_mutex))
36 for (k = 0; k < 16; k++)
37 if (firesat->channel[k].active == 0) {
38 firesat->channel[k].active = 1;
39 c = &firesat->channel[k];
43 mutex_unlock(&firesat->demux_mutex);
47 static int firesat_channel_collect(struct firesat *firesat, int *pidc, u16 pid[])
51 if (mutex_lock_interruptible(&firesat->demux_mutex))
54 for (k = 0; k < 16; k++)
55 if (firesat->channel[k].active == 1)
56 pid[l++] = firesat->channel[k].pid;
58 mutex_unlock(&firesat->demux_mutex);
65 static int firesat_channel_release(struct firesat *firesat,
66 struct firesat_channel *channel)
68 if (mutex_lock_interruptible(&firesat->demux_mutex))
73 mutex_unlock(&firesat->demux_mutex);
77 int firesat_start_feed(struct dvb_demux_feed *dvbdmxfeed)
79 struct firesat *firesat = (struct firesat*)dvbdmxfeed->demux->priv;
80 struct firesat_channel *channel;
84 // printk(KERN_INFO "%s (pid %u)\n", __func__, dvbdmxfeed->pid);
86 switch (dvbdmxfeed->type) {
91 printk(KERN_ERR "%s: invalid type %u\n",
92 __func__, dvbdmxfeed->type);
96 if (dvbdmxfeed->type == DMX_TYPE_TS) {
97 switch (dvbdmxfeed->pes_type) {
98 case DMX_TS_PES_VIDEO:
99 case DMX_TS_PES_AUDIO:
100 case DMX_TS_PES_TELETEXT:
102 case DMX_TS_PES_OTHER:
103 //Dirty fix to keep firesat->channel pid-list up to date
105 if(firesat->channel[k].active == 0)
106 firesat->channel[k].pid =
110 channel = firesat_channel_allocate(firesat);
113 printk(KERN_ERR "%s: invalid pes type %u\n",
114 __func__, dvbdmxfeed->pes_type);
118 channel = firesat_channel_allocate(firesat);
122 printk(KERN_ERR "%s: busy!\n", __func__);
126 dvbdmxfeed->priv = channel;
128 channel->dvbdmxfeed = dvbdmxfeed;
129 channel->pid = dvbdmxfeed->pid;
130 channel->type = dvbdmxfeed->type;
131 channel->firesat = firesat;
133 if (firesat_channel_collect(firesat, &pidc, pids)) {
134 firesat_channel_release(firesat, channel);
135 printk(KERN_ERR "%s: could not collect pids!\n", __func__);
139 if(dvbdmxfeed->pid == 8192) {
140 if((k = AVCTuner_GetTS(firesat))) {
141 firesat_channel_release(firesat, channel);
142 printk("%s: AVCTuner_GetTS failed with error %d\n",
148 if((k = AVCTuner_SetPIDs(firesat, pidc, pids))) {
149 firesat_channel_release(firesat, channel);
150 printk("%s: AVCTuner_SetPIDs failed with error %d\n",
159 int firesat_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
161 struct dvb_demux *demux = dvbdmxfeed->demux;
162 struct firesat *firesat = (struct firesat*)demux->priv;
163 struct firesat_channel *c = dvbdmxfeed->priv;
167 //printk(KERN_INFO "%s (pid %u)\n", __func__, dvbdmxfeed->pid);
169 if (dvbdmxfeed->type == DMX_TYPE_TS && !((dvbdmxfeed->ts_type & TS_PACKET) &&
170 (demux->dmx.frontend->source != DMX_MEMORY_FE))) {
172 if (dvbdmxfeed->ts_type & TS_DECODER) {
174 if (dvbdmxfeed->pes_type >= DMX_TS_PES_OTHER ||
175 !demux->pesfilter[dvbdmxfeed->pes_type])
179 demux->pids[dvbdmxfeed->pes_type] |= 0x8000;
180 demux->pesfilter[dvbdmxfeed->pes_type] = 0;
183 if (!(dvbdmxfeed->ts_type & TS_DECODER &&
184 dvbdmxfeed->pes_type < DMX_TS_PES_OTHER))
189 if (mutex_lock_interruptible(&firesat->demux_mutex))
192 /* list except channel to be removed */
193 for (k = 0, l = 0; k < 16; k++)
194 if (firesat->channel[k].active == 1) {
195 if (&firesat->channel[k] != c)
196 pids[l++] = firesat->channel[k].pid;
198 firesat->channel[k].active = 0;
201 k = AVCTuner_SetPIDs(firesat, l, pids);
205 mutex_unlock(&firesat->demux_mutex);
209 int firesat_dvbdev_init(struct firesat *firesat,
211 struct dvb_frontend *fe)
215 firesat->adapter = kmalloc(sizeof(*firesat->adapter), GFP_KERNEL);
216 if (!firesat->adapter) {
217 printk(KERN_ERR "firedtv: couldn't allocate memory\n");
221 result = DVB_REGISTER_ADAPTER(firesat->adapter,
222 firedtv_model_names[firesat->type],
223 THIS_MODULE, dev, adapter_nr);
225 printk(KERN_ERR "firedtv: dvb_register_adapter failed\n");
226 kfree(firesat->adapter);
230 memset(&firesat->demux, 0, sizeof(struct dvb_demux));
231 firesat->demux.dmx.capabilities = 0/*DMX_TS_FILTERING | DMX_SECTION_FILTERING*/;
233 firesat->demux.priv = (void *)firesat;
234 firesat->demux.filternum = 16;
235 firesat->demux.feednum = 16;
236 firesat->demux.start_feed = firesat_start_feed;
237 firesat->demux.stop_feed = firesat_stop_feed;
238 firesat->demux.write_to_decoder = NULL;
240 if ((result = dvb_dmx_init(&firesat->demux)) < 0) {
241 printk("%s: dvb_dmx_init failed: error %d\n", __func__,
244 dvb_unregister_adapter(firesat->adapter);
249 firesat->dmxdev.filternum = 16;
250 firesat->dmxdev.demux = &firesat->demux.dmx;
251 firesat->dmxdev.capabilities = 0;
253 if ((result = dvb_dmxdev_init(&firesat->dmxdev, firesat->adapter)) < 0) {
254 printk("%s: dvb_dmxdev_init failed: error %d\n",
257 dvb_dmx_release(&firesat->demux);
258 dvb_unregister_adapter(firesat->adapter);
263 firesat->frontend.source = DMX_FRONTEND_0;
265 if ((result = firesat->demux.dmx.add_frontend(&firesat->demux.dmx,
266 &firesat->frontend)) < 0) {
267 printk("%s: dvb_dmx_init failed: error %d\n", __func__,
270 dvb_dmxdev_release(&firesat->dmxdev);
271 dvb_dmx_release(&firesat->demux);
272 dvb_unregister_adapter(firesat->adapter);
277 if ((result = firesat->demux.dmx.connect_frontend(&firesat->demux.dmx,
278 &firesat->frontend)) < 0) {
279 printk("%s: dvb_dmx_init failed: error %d\n", __func__,
282 firesat->demux.dmx.remove_frontend(&firesat->demux.dmx, &firesat->frontend);
283 dvb_dmxdev_release(&firesat->dmxdev);
284 dvb_dmx_release(&firesat->demux);
285 dvb_unregister_adapter(firesat->adapter);
290 dvb_net_init(firesat->adapter, &firesat->dvbnet, &firesat->demux.dmx);
292 // fe->ops = firesat_ops;
293 // fe->dvb = firesat->adapter;
294 firesat_frontend_attach(firesat, fe);
296 fe->sec_priv = firesat; //IMPORTANT, functions depend on this!!!
297 if ((result= dvb_register_frontend(firesat->adapter, fe)) < 0) {
298 printk("%s: dvb_register_frontend_new failed: error %d\n", __func__, result);
303 firesat_ca_init(firesat);