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
) {
38 firesat
->channel
[k
].active
= true;
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
)
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
))
71 channel
->active
= false;
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 switch (dvbdmxfeed
->type
) {
89 printk(KERN_ERR
"%s: invalid type %u\n",
90 __func__
, dvbdmxfeed
->type
);
94 if (dvbdmxfeed
->type
== DMX_TYPE_TS
) {
95 switch (dvbdmxfeed
->pes_type
) {
96 case DMX_TS_PES_VIDEO
:
97 case DMX_TS_PES_AUDIO
:
98 case DMX_TS_PES_TELETEXT
:
100 case DMX_TS_PES_OTHER
:
101 //Dirty fix to keep firesat->channel pid-list up to date
103 if (!firesat
->channel
[k
].active
)
104 firesat
->channel
[k
].pid
=
108 channel
= firesat_channel_allocate(firesat
);
111 printk(KERN_ERR
"%s: invalid pes type %u\n",
112 __func__
, dvbdmxfeed
->pes_type
);
116 channel
= firesat_channel_allocate(firesat
);
120 printk(KERN_ERR
"%s: busy!\n", __func__
);
124 dvbdmxfeed
->priv
= channel
;
125 channel
->pid
= dvbdmxfeed
->pid
;
127 if (firesat_channel_collect(firesat
, &pidc
, pids
)) {
128 firesat_channel_release(firesat
, channel
);
129 printk(KERN_ERR
"%s: could not collect pids!\n", __func__
);
133 if (dvbdmxfeed
->pid
== 8192) {
134 k
= avc_tuner_get_ts(firesat
);
136 firesat_channel_release(firesat
, channel
);
137 printk("%s: AVCTuner_GetTS failed with error %d\n",
142 k
= avc_tuner_set_pids(firesat
, pidc
, pids
);
144 firesat_channel_release(firesat
, channel
);
145 printk("%s: AVCTuner_SetPIDs failed with error %d\n",
154 int firesat_stop_feed(struct dvb_demux_feed
*dvbdmxfeed
)
156 struct dvb_demux
*demux
= dvbdmxfeed
->demux
;
157 struct firesat
*firesat
= (struct firesat
*)demux
->priv
;
158 struct firesat_channel
*c
= dvbdmxfeed
->priv
;
162 if (dvbdmxfeed
->type
== DMX_TYPE_TS
&& !((dvbdmxfeed
->ts_type
& TS_PACKET
) &&
163 (demux
->dmx
.frontend
->source
!= DMX_MEMORY_FE
))) {
165 if (dvbdmxfeed
->ts_type
& TS_DECODER
) {
167 if (dvbdmxfeed
->pes_type
>= DMX_TS_PES_OTHER
||
168 !demux
->pesfilter
[dvbdmxfeed
->pes_type
])
172 demux
->pids
[dvbdmxfeed
->pes_type
] |= 0x8000;
173 demux
->pesfilter
[dvbdmxfeed
->pes_type
] = NULL
;
176 if (!(dvbdmxfeed
->ts_type
& TS_DECODER
&&
177 dvbdmxfeed
->pes_type
< DMX_TS_PES_OTHER
))
182 if (mutex_lock_interruptible(&firesat
->demux_mutex
))
185 /* list except channel to be removed */
186 for (k
= 0, l
= 0; k
< 16; k
++)
187 if (firesat
->channel
[k
].active
) {
188 if (&firesat
->channel
[k
] != c
)
189 pids
[l
++] = firesat
->channel
[k
].pid
;
191 firesat
->channel
[k
].active
= false;
194 k
= avc_tuner_set_pids(firesat
, l
, pids
);
198 mutex_unlock(&firesat
->demux_mutex
);
202 int firesat_dvbdev_init(struct firesat
*firesat
, struct device
*dev
)
206 err
= DVB_REGISTER_ADAPTER(&firesat
->adapter
,
207 firedtv_model_names
[firesat
->type
],
208 THIS_MODULE
, dev
, adapter_nr
);
212 /*DMX_TS_FILTERING | DMX_SECTION_FILTERING*/
213 firesat
->demux
.dmx
.capabilities
= 0;
215 firesat
->demux
.priv
= (void *)firesat
;
216 firesat
->demux
.filternum
= 16;
217 firesat
->demux
.feednum
= 16;
218 firesat
->demux
.start_feed
= firesat_start_feed
;
219 firesat
->demux
.stop_feed
= firesat_stop_feed
;
220 firesat
->demux
.write_to_decoder
= NULL
;
222 err
= dvb_dmx_init(&firesat
->demux
);
224 goto fail_unreg_adapter
;
226 firesat
->dmxdev
.filternum
= 16;
227 firesat
->dmxdev
.demux
= &firesat
->demux
.dmx
;
228 firesat
->dmxdev
.capabilities
= 0;
230 err
= dvb_dmxdev_init(&firesat
->dmxdev
, &firesat
->adapter
);
232 goto fail_dmx_release
;
234 firesat
->frontend
.source
= DMX_FRONTEND_0
;
236 err
= firesat
->demux
.dmx
.add_frontend(&firesat
->demux
.dmx
,
239 goto fail_dmxdev_release
;
241 err
= firesat
->demux
.dmx
.connect_frontend(&firesat
->demux
.dmx
,
244 goto fail_rem_frontend
;
246 dvb_net_init(&firesat
->adapter
, &firesat
->dvbnet
, &firesat
->demux
.dmx
);
248 firesat_frontend_init(firesat
);
249 err
= dvb_register_frontend(&firesat
->adapter
, &firesat
->fe
);
251 goto fail_net_release
;
253 err
= firesat_ca_register(firesat
);
255 dev_info(dev
, "Conditional Access Module not enabled\n");
260 dvb_net_release(&firesat
->dvbnet
);
261 firesat
->demux
.dmx
.close(&firesat
->demux
.dmx
);
263 firesat
->demux
.dmx
.remove_frontend(&firesat
->demux
.dmx
,
266 dvb_dmxdev_release(&firesat
->dmxdev
);
268 dvb_dmx_release(&firesat
->demux
);
270 dvb_unregister_adapter(&firesat
->adapter
);
272 dev_err(dev
, "DVB initialization failed\n");