firesat: avc resend
[linux-2.6-block.git] / drivers / media / dvb / firesat / firesat_dvb.c
CommitLineData
df4846c3
HK
1/*
2 * FireSAT DVB driver
3 *
4 * Copyright (c) ?
5 * Copyright (c) 2008 Henrik Kurelid <henrik@kurelid.se>
6 *
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.
11 */
12
c81c8b68
GKH
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>
c81c8b68
GKH
21#include <ieee1394_hotplug.h>
22#include <nodemgr.h>
23#include <highlevel.h>
24#include <ohci1394.h>
25#include <hosts.h>
26#include <dvbdev.h>
27
28#include "firesat.h"
29#include "avc_api.h"
30#include "cmp.h"
31#include "firesat-rc.h"
32#include "firesat-ci.h"
33
34DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
35
36static struct firesat_channel *firesat_channel_allocate(struct firesat *firesat)
37{
38 int k;
39
df4846c3 40 //printk(KERN_INFO "%s\n", __func__);
c81c8b68
GKH
41
42 if (down_interruptible(&firesat->demux_sem))
43 return NULL;
44
45 for (k = 0; k < 16; k++) {
df4846c3 46 //printk(KERN_INFO "%s: channel %d: active = %d, pid = 0x%x\n",__func__,k,firesat->channel[k].active,firesat->channel[k].pid);
c81c8b68
GKH
47
48 if (firesat->channel[k].active == 0) {
49 firesat->channel[k].active = 1;
50 up(&firesat->demux_sem);
51 return &firesat->channel[k];
52 }
53 }
54
55 up(&firesat->demux_sem);
56 return NULL; // no more channels available
57}
58
59static int firesat_channel_collect(struct firesat *firesat, int *pidc, u16 pid[])
60{
61 int k, l = 0;
62
63 if (down_interruptible(&firesat->demux_sem))
64 return -EINTR;
65
66 for (k = 0; k < 16; k++)
67 if (firesat->channel[k].active == 1)
68 pid[l++] = firesat->channel[k].pid;
69
70 up(&firesat->demux_sem);
71
72 *pidc = l;
73
74 return 0;
75}
76
77static int firesat_channel_release(struct firesat *firesat,
78 struct firesat_channel *channel)
79{
80 if (down_interruptible(&firesat->demux_sem))
81 return -EINTR;
82
83 channel->active = 0;
84
85 up(&firesat->demux_sem);
86 return 0;
87}
88
89int firesat_start_feed(struct dvb_demux_feed *dvbdmxfeed)
90{
91 struct firesat *firesat = (struct firesat*)dvbdmxfeed->demux->priv;
92 struct firesat_channel *channel;
93 int pidc,k;
94 u16 pids[16];
95
df4846c3 96// printk(KERN_INFO "%s (pid %u)\n", __func__, dvbdmxfeed->pid);
c81c8b68
GKH
97
98 switch (dvbdmxfeed->type) {
99 case DMX_TYPE_TS:
100 case DMX_TYPE_SEC:
101 break;
102 default:
df4846c3
HK
103 printk(KERN_ERR "%s: invalid type %u\n",
104 __func__, dvbdmxfeed->type);
c81c8b68
GKH
105 return -EINVAL;
106 }
107
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:
113 case DMX_TS_PES_PCR:
114 case DMX_TS_PES_OTHER:
115 //Dirty fix to keep firesat->channel pid-list up to date
116 for(k=0;k<16;k++){
117 if(firesat->channel[k].active == 0)
118 firesat->channel[k].pid =
119 dvbdmxfeed->pid;
120 break;
121 }
122 channel = firesat_channel_allocate(firesat);
123 break;
124 default:
df4846c3
HK
125 printk(KERN_ERR "%s: invalid pes type %u\n",
126 __func__, dvbdmxfeed->pes_type);
c81c8b68
GKH
127 return -EINVAL;
128 }
129 } else {
130 channel = firesat_channel_allocate(firesat);
131 }
132
133 if (!channel) {
df4846c3 134 printk(KERN_ERR "%s: busy!\n", __func__);
c81c8b68
GKH
135 return -EBUSY;
136 }
137
138 dvbdmxfeed->priv = channel;
139
140 channel->dvbdmxfeed = dvbdmxfeed;
141 channel->pid = dvbdmxfeed->pid;
142 channel->type = dvbdmxfeed->type;
143 channel->firesat = firesat;
144
145 if (firesat_channel_collect(firesat, &pidc, pids)) {
146 firesat_channel_release(firesat, channel);
df4846c3 147 printk(KERN_ERR "%s: could not collect pids!\n", __func__);
c81c8b68
GKH
148 return -EINTR;
149 }
150
151 if(dvbdmxfeed->pid == 8192) {
df4846c3 152 if((k = AVCTuner_GetTS(firesat))) {
c81c8b68
GKH
153 firesat_channel_release(firesat, channel);
154 printk("%s: AVCTuner_GetTS failed with error %d\n",
df4846c3 155 __func__, k);
c81c8b68
GKH
156 return k;
157 }
158 }
159 else {
df4846c3 160 if((k = AVCTuner_SetPIDs(firesat, pidc, pids))) {
c81c8b68
GKH
161 firesat_channel_release(firesat, channel);
162 printk("%s: AVCTuner_SetPIDs failed with error %d\n",
df4846c3 163 __func__, k);
c81c8b68
GKH
164 return k;
165 }
166 }
167
168 return 0;
169}
170
171int firesat_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
172{
173 struct dvb_demux *demux = dvbdmxfeed->demux;
174 struct firesat *firesat = (struct firesat*)demux->priv;
175 int k, l = 0;
176 u16 pids[16];
177
df4846c3 178 //printk(KERN_INFO "%s (pid %u)\n", __func__, dvbdmxfeed->pid);
c81c8b68
GKH
179
180 if (dvbdmxfeed->type == DMX_TYPE_TS && !((dvbdmxfeed->ts_type & TS_PACKET) &&
181 (demux->dmx.frontend->source != DMX_MEMORY_FE))) {
182
183 if (dvbdmxfeed->ts_type & TS_DECODER) {
184
185 if (dvbdmxfeed->pes_type >= DMX_TS_PES_OTHER ||
186 !demux->pesfilter[dvbdmxfeed->pes_type])
187
188 return -EINVAL;
189
190 demux->pids[dvbdmxfeed->pes_type] |= 0x8000;
191 demux->pesfilter[dvbdmxfeed->pes_type] = 0;
192 }
193
194 if (!(dvbdmxfeed->ts_type & TS_DECODER &&
195 dvbdmxfeed->pes_type < DMX_TS_PES_OTHER))
196
197 return 0;
198 }
199
200 if (down_interruptible(&firesat->demux_sem))
201 return -EINTR;
202
203
204 // list except channel to be removed
205 for (k = 0; k < 16; k++)
df4846c3 206 if (firesat->channel[k].active == 1) {
c81c8b68
GKH
207 if (&firesat->channel[k] !=
208 (struct firesat_channel *)dvbdmxfeed->priv)
209 pids[l++] = firesat->channel[k].pid;
210 else
211 firesat->channel[k].active = 0;
df4846c3 212 }
c81c8b68
GKH
213
214 if ((k = AVCTuner_SetPIDs(firesat, l, pids))) {
215 up(&firesat->demux_sem);
216 return k;
217 }
218
219 ((struct firesat_channel *)dvbdmxfeed->priv)->active = 0;
220
221 up(&firesat->demux_sem);
222
223 return 0;
224}
225
226int firesat_dvbdev_init(struct firesat *firesat,
227 struct device *dev,
228 struct dvb_frontend *fe)
229{
230 int result;
231
c81c8b68
GKH
232#if 0
233 switch (firesat->type) {
234 case FireSAT_DVB_S:
235 firesat->model_name = "FireSAT DVB-S";
236 firesat->frontend_info = &firesat_S_frontend_info;
237 break;
238 case FireSAT_DVB_C:
239 firesat->model_name = "FireSAT DVB-C";
240 firesat->frontend_info = &firesat_C_frontend_info;
241 break;
242 case FireSAT_DVB_T:
243 firesat->model_name = "FireSAT DVB-T";
244 firesat->frontend_info = &firesat_T_frontend_info;
245 break;
246 default:
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;
251 }
252#endif
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);
258 kfree(firesat);
259 continue;
260 }
261*/
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);
266 kfree(firesat);
267 return -ENOMEM;
268 }
269
df4846c3 270 if ((result = DVB_REGISTER_ADAPTER(firesat->adapter,
c81c8b68
GKH
271 firesat->model_name,
272 THIS_MODULE,
273 dev, adapter_nr)) < 0) {
274
275 printk("%s: dvb_register_adapter failed: error %d\n", __func__, result);
276#if 0
277 /* ### cleanup */
278 spin_lock_irqsave(&firesat_list_lock, flags);
279 list_del(&firesat->list);
280 spin_unlock_irqrestore(&firesat_list_lock, flags);
281#endif
282 kfree(firesat);
283
284 return result;
285 }
286
df4846c3 287 memset(&firesat->demux, 0, sizeof(struct dvb_demux));
c81c8b68
GKH
288 firesat->demux.dmx.capabilities = 0/*DMX_TS_FILTERING | DMX_SECTION_FILTERING*/;
289
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;
296
297 if ((result = dvb_dmx_init(&firesat->demux)) < 0) {
298 printk("%s: dvb_dmx_init failed: error %d\n", __func__,
299 result);
300
301 dvb_unregister_adapter(firesat->adapter);
302
303 return result;
304 }
305
306 firesat->dmxdev.filternum = 16;
307 firesat->dmxdev.demux = &firesat->demux.dmx;
308 firesat->dmxdev.capabilities = 0;
309
310 if ((result = dvb_dmxdev_init(&firesat->dmxdev, firesat->adapter)) < 0) {
311 printk("%s: dvb_dmxdev_init failed: error %d\n",
312 __func__, result);
313
314 dvb_dmx_release(&firesat->demux);
315 dvb_unregister_adapter(firesat->adapter);
316
317 return result;
318 }
319
320 firesat->frontend.source = DMX_FRONTEND_0;
321
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__,
325 result);
326
327 dvb_dmxdev_release(&firesat->dmxdev);
328 dvb_dmx_release(&firesat->demux);
329 dvb_unregister_adapter(firesat->adapter);
330
331 return result;
332 }
333
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__,
337 result);
338
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);
343
344 return result;
345 }
346
347 dvb_net_init(firesat->adapter, &firesat->dvbnet, &firesat->demux.dmx);
348
349// fe->ops = firesat_ops;
350// fe->dvb = firesat->adapter;
351 firesat_frontend_attach(firesat, fe);
352
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);
356 /* ### cleanup */
357 return result;
358 }
359
c81c8b68
GKH
360 firesat_ca_init(firesat);
361
362 return 0;
363}
df4846c3
HK
364
365