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/init.h>
14 #include <linux/slab.h>
15 #include <linux/wait.h>
16 #include <linux/module.h>
17 #include <linux/delay.h>
18 #include <linux/time.h>
19 #include <linux/errno.h>
20 #include <linux/interrupt.h>
21 #include <ieee1394_hotplug.h>
23 #include <highlevel.h>
31 #include "firesat-rc.h"
32 #include "firesat-ci.h"
34 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr
);
36 static struct firesat_channel
*firesat_channel_allocate(struct firesat
*firesat
)
40 //printk(KERN_INFO "%s\n", __func__);
42 if (down_interruptible(&firesat
->demux_sem
))
45 for (k
= 0; k
< 16; k
++) {
46 //printk(KERN_INFO "%s: channel %d: active = %d, pid = 0x%x\n",__func__,k,firesat->channel[k].active,firesat->channel[k].pid);
48 if (firesat
->channel
[k
].active
== 0) {
49 firesat
->channel
[k
].active
= 1;
50 up(&firesat
->demux_sem
);
51 return &firesat
->channel
[k
];
55 up(&firesat
->demux_sem
);
56 return NULL
; // no more channels available
59 static int firesat_channel_collect(struct firesat
*firesat
, int *pidc
, u16 pid
[])
63 if (down_interruptible(&firesat
->demux_sem
))
66 for (k
= 0; k
< 16; k
++)
67 if (firesat
->channel
[k
].active
== 1)
68 pid
[l
++] = firesat
->channel
[k
].pid
;
70 up(&firesat
->demux_sem
);
77 static int firesat_channel_release(struct firesat
*firesat
,
78 struct firesat_channel
*channel
)
80 if (down_interruptible(&firesat
->demux_sem
))
85 up(&firesat
->demux_sem
);
89 int firesat_start_feed(struct dvb_demux_feed
*dvbdmxfeed
)
91 struct firesat
*firesat
= (struct firesat
*)dvbdmxfeed
->demux
->priv
;
92 struct firesat_channel
*channel
;
96 // printk(KERN_INFO "%s (pid %u)\n", __func__, dvbdmxfeed->pid);
98 switch (dvbdmxfeed
->type
) {
103 printk(KERN_ERR
"%s: invalid type %u\n",
104 __func__
, dvbdmxfeed
->type
);
108 if (dvbdmxfeed
->type
== DMX_TYPE_TS
) {
109 switch (dvbdmxfeed
->pes_type
) {
110 case DMX_TS_PES_VIDEO
:
111 case DMX_TS_PES_AUDIO
:
112 case DMX_TS_PES_TELETEXT
:
114 case DMX_TS_PES_OTHER
:
115 //Dirty fix to keep firesat->channel pid-list up to date
117 if(firesat
->channel
[k
].active
== 0)
118 firesat
->channel
[k
].pid
=
122 channel
= firesat_channel_allocate(firesat
);
125 printk(KERN_ERR
"%s: invalid pes type %u\n",
126 __func__
, dvbdmxfeed
->pes_type
);
130 channel
= firesat_channel_allocate(firesat
);
134 printk(KERN_ERR
"%s: busy!\n", __func__
);
138 dvbdmxfeed
->priv
= channel
;
140 channel
->dvbdmxfeed
= dvbdmxfeed
;
141 channel
->pid
= dvbdmxfeed
->pid
;
142 channel
->type
= dvbdmxfeed
->type
;
143 channel
->firesat
= firesat
;
145 if (firesat_channel_collect(firesat
, &pidc
, pids
)) {
146 firesat_channel_release(firesat
, channel
);
147 printk(KERN_ERR
"%s: could not collect pids!\n", __func__
);
151 if(dvbdmxfeed
->pid
== 8192) {
152 if((k
= AVCTuner_GetTS(firesat
))) {
153 firesat_channel_release(firesat
, channel
);
154 printk("%s: AVCTuner_GetTS failed with error %d\n",
160 if((k
= AVCTuner_SetPIDs(firesat
, pidc
, pids
))) {
161 firesat_channel_release(firesat
, channel
);
162 printk("%s: AVCTuner_SetPIDs failed with error %d\n",
171 int firesat_stop_feed(struct dvb_demux_feed
*dvbdmxfeed
)
173 struct dvb_demux
*demux
= dvbdmxfeed
->demux
;
174 struct firesat
*firesat
= (struct firesat
*)demux
->priv
;
178 //printk(KERN_INFO "%s (pid %u)\n", __func__, dvbdmxfeed->pid);
180 if (dvbdmxfeed
->type
== DMX_TYPE_TS
&& !((dvbdmxfeed
->ts_type
& TS_PACKET
) &&
181 (demux
->dmx
.frontend
->source
!= DMX_MEMORY_FE
))) {
183 if (dvbdmxfeed
->ts_type
& TS_DECODER
) {
185 if (dvbdmxfeed
->pes_type
>= DMX_TS_PES_OTHER
||
186 !demux
->pesfilter
[dvbdmxfeed
->pes_type
])
190 demux
->pids
[dvbdmxfeed
->pes_type
] |= 0x8000;
191 demux
->pesfilter
[dvbdmxfeed
->pes_type
] = 0;
194 if (!(dvbdmxfeed
->ts_type
& TS_DECODER
&&
195 dvbdmxfeed
->pes_type
< DMX_TS_PES_OTHER
))
200 if (down_interruptible(&firesat
->demux_sem
))
204 // list except channel to be removed
205 for (k
= 0; k
< 16; k
++)
206 if (firesat
->channel
[k
].active
== 1) {
207 if (&firesat
->channel
[k
] !=
208 (struct firesat_channel
*)dvbdmxfeed
->priv
)
209 pids
[l
++] = firesat
->channel
[k
].pid
;
211 firesat
->channel
[k
].active
= 0;
214 if ((k
= AVCTuner_SetPIDs(firesat
, l
, pids
))) {
215 up(&firesat
->demux_sem
);
219 ((struct firesat_channel
*)dvbdmxfeed
->priv
)->active
= 0;
221 up(&firesat
->demux_sem
);
226 int firesat_dvbdev_init(struct firesat
*firesat
,
228 struct dvb_frontend
*fe
)
233 switch (firesat
->type
) {
235 firesat
->model_name
= "FireSAT DVB-S";
236 firesat
->frontend_info
= &firesat_S_frontend_info
;
239 firesat
->model_name
= "FireSAT DVB-C";
240 firesat
->frontend_info
= &firesat_C_frontend_info
;
243 firesat
->model_name
= "FireSAT DVB-T";
244 firesat
->frontend_info
= &firesat_T_frontend_info
;
247 printk("%s: unknown model type 0x%x on subunit %d!\n",
248 __func__
, firesat
->type
,subunit
);
249 firesat
->model_name
= "Unknown";
250 firesat
->frontend_info
= NULL
;
253 /* // ------- CRAP -----------
254 if (!firesat->frontend_info) {
255 spin_lock_irqsave(&firesat_list_lock, flags);
256 list_del(&firesat->list);
257 spin_unlock_irqrestore(&firesat_list_lock, flags);
262 //initialising firesat->adapter before calling dvb_register_adapter
263 if (!(firesat
->adapter
= kmalloc(sizeof (struct dvb_adapter
), GFP_KERNEL
))) {
264 printk("%s: couldn't allocate memory.\n", __func__
);
265 kfree(firesat
->adapter
);
270 if ((result
= DVB_REGISTER_ADAPTER(firesat
->adapter
,
273 dev
, adapter_nr
)) < 0) {
275 printk("%s: dvb_register_adapter failed: error %d\n", __func__
, result
);
278 spin_lock_irqsave(&firesat_list_lock
, flags
);
279 list_del(&firesat
->list
);
280 spin_unlock_irqrestore(&firesat_list_lock
, flags
);
287 memset(&firesat
->demux
, 0, sizeof(struct dvb_demux
));
288 firesat
->demux
.dmx
.capabilities
= 0/*DMX_TS_FILTERING | DMX_SECTION_FILTERING*/;
290 firesat
->demux
.priv
= (void *)firesat
;
291 firesat
->demux
.filternum
= 16;
292 firesat
->demux
.feednum
= 16;
293 firesat
->demux
.start_feed
= firesat_start_feed
;
294 firesat
->demux
.stop_feed
= firesat_stop_feed
;
295 firesat
->demux
.write_to_decoder
= NULL
;
297 if ((result
= dvb_dmx_init(&firesat
->demux
)) < 0) {
298 printk("%s: dvb_dmx_init failed: error %d\n", __func__
,
301 dvb_unregister_adapter(firesat
->adapter
);
306 firesat
->dmxdev
.filternum
= 16;
307 firesat
->dmxdev
.demux
= &firesat
->demux
.dmx
;
308 firesat
->dmxdev
.capabilities
= 0;
310 if ((result
= dvb_dmxdev_init(&firesat
->dmxdev
, firesat
->adapter
)) < 0) {
311 printk("%s: dvb_dmxdev_init failed: error %d\n",
314 dvb_dmx_release(&firesat
->demux
);
315 dvb_unregister_adapter(firesat
->adapter
);
320 firesat
->frontend
.source
= DMX_FRONTEND_0
;
322 if ((result
= firesat
->demux
.dmx
.add_frontend(&firesat
->demux
.dmx
,
323 &firesat
->frontend
)) < 0) {
324 printk("%s: dvb_dmx_init failed: error %d\n", __func__
,
327 dvb_dmxdev_release(&firesat
->dmxdev
);
328 dvb_dmx_release(&firesat
->demux
);
329 dvb_unregister_adapter(firesat
->adapter
);
334 if ((result
= firesat
->demux
.dmx
.connect_frontend(&firesat
->demux
.dmx
,
335 &firesat
->frontend
)) < 0) {
336 printk("%s: dvb_dmx_init failed: error %d\n", __func__
,
339 firesat
->demux
.dmx
.remove_frontend(&firesat
->demux
.dmx
, &firesat
->frontend
);
340 dvb_dmxdev_release(&firesat
->dmxdev
);
341 dvb_dmx_release(&firesat
->demux
);
342 dvb_unregister_adapter(firesat
->adapter
);
347 dvb_net_init(firesat
->adapter
, &firesat
->dvbnet
, &firesat
->demux
.dmx
);
349 // fe->ops = firesat_ops;
350 // fe->dvb = firesat->adapter;
351 firesat_frontend_attach(firesat
, fe
);
353 fe
->sec_priv
= firesat
; //IMPORTANT, functions depend on this!!!
354 if ((result
= dvb_register_frontend(firesat
->adapter
, fe
)) < 0) {
355 printk("%s: dvb_register_frontend_new failed: error %d\n", __func__
, result
);
360 firesat_ca_init(firesat
);