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/bitops.h>
14 #include <linux/device.h>
15 #include <linux/errno.h>
16 #include <linux/kernel.h>
17 #include <linux/mod_devicetable.h>
18 #include <linux/module.h>
19 #include <linux/mutex.h>
20 #include <linux/slab.h>
21 #include <linux/string.h>
22 #include <linux/types.h>
23 #include <linux/wait.h>
24 #include <linux/workqueue.h>
27 #include <dvb_demux.h>
29 #include <dvb_frontend.h>
33 static int alloc_channel(struct firedtv
*fdtv
)
37 for (i
= 0; i
< 16; i
++)
38 if (!__test_and_set_bit(i
, &fdtv
->channel_active
))
43 static void collect_channels(struct firedtv
*fdtv
, int *pidc
, u16 pid
[])
47 for (i
= 0, n
= 0; i
< 16; i
++)
48 if (test_bit(i
, &fdtv
->channel_active
))
49 pid
[n
++] = fdtv
->channel_pid
[i
];
53 static inline void dealloc_channel(struct firedtv
*fdtv
, int i
)
55 __clear_bit(i
, &fdtv
->channel_active
);
58 int fdtv_start_feed(struct dvb_demux_feed
*dvbdmxfeed
)
60 struct firedtv
*fdtv
= dvbdmxfeed
->demux
->priv
;
64 switch (dvbdmxfeed
->type
) {
69 dev_err(fdtv
->device
, "can't start dmx feed: invalid type %u\n",
74 if (mutex_lock_interruptible(&fdtv
->demux_mutex
))
77 if (dvbdmxfeed
->type
== DMX_TYPE_TS
) {
78 switch (dvbdmxfeed
->pes_type
) {
79 case DMX_TS_PES_VIDEO
:
80 case DMX_TS_PES_AUDIO
:
81 case DMX_TS_PES_TELETEXT
:
83 case DMX_TS_PES_OTHER
:
84 c
= alloc_channel(fdtv
);
88 "can't start dmx feed: invalid pes type %u\n",
89 dvbdmxfeed
->pes_type
);
94 c
= alloc_channel(fdtv
);
98 dev_err(fdtv
->device
, "can't start dmx feed: busy\n");
103 dvbdmxfeed
->priv
= (typeof(dvbdmxfeed
->priv
))(unsigned long)c
;
104 fdtv
->channel_pid
[c
] = dvbdmxfeed
->pid
;
105 collect_channels(fdtv
, &pidc
, pids
);
107 if (dvbdmxfeed
->pid
== 8192) {
108 ret
= avc_tuner_get_ts(fdtv
);
110 dealloc_channel(fdtv
, c
);
111 dev_err(fdtv
->device
, "can't get TS\n");
115 ret
= avc_tuner_set_pids(fdtv
, pidc
, pids
);
117 dealloc_channel(fdtv
, c
);
118 dev_err(fdtv
->device
, "can't set PIDs\n");
123 mutex_unlock(&fdtv
->demux_mutex
);
128 int fdtv_stop_feed(struct dvb_demux_feed
*dvbdmxfeed
)
130 struct dvb_demux
*demux
= dvbdmxfeed
->demux
;
131 struct firedtv
*fdtv
= demux
->priv
;
135 if (dvbdmxfeed
->type
== DMX_TYPE_TS
&&
136 !((dvbdmxfeed
->ts_type
& TS_PACKET
) &&
137 (demux
->dmx
.frontend
->source
!= DMX_MEMORY_FE
))) {
139 if (dvbdmxfeed
->ts_type
& TS_DECODER
) {
140 if (dvbdmxfeed
->pes_type
>= DMX_TS_PES_OTHER
||
141 !demux
->pesfilter
[dvbdmxfeed
->pes_type
])
144 demux
->pids
[dvbdmxfeed
->pes_type
] |= 0x8000;
145 demux
->pesfilter
[dvbdmxfeed
->pes_type
] = NULL
;
148 if (!(dvbdmxfeed
->ts_type
& TS_DECODER
&&
149 dvbdmxfeed
->pes_type
< DMX_TS_PES_OTHER
))
153 if (mutex_lock_interruptible(&fdtv
->demux_mutex
))
156 c
= (unsigned long)dvbdmxfeed
->priv
;
157 dealloc_channel(fdtv
, c
);
158 collect_channels(fdtv
, &pidc
, pids
);
160 ret
= avc_tuner_set_pids(fdtv
, pidc
, pids
);
162 mutex_unlock(&fdtv
->demux_mutex
);
167 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr
);
169 int fdtv_dvb_register(struct firedtv
*fdtv
)
173 err
= dvb_register_adapter(&fdtv
->adapter
, fdtv_model_names
[fdtv
->type
],
174 THIS_MODULE
, fdtv
->device
, adapter_nr
);
178 /*DMX_TS_FILTERING | DMX_SECTION_FILTERING*/
179 fdtv
->demux
.dmx
.capabilities
= 0;
181 fdtv
->demux
.priv
= fdtv
;
182 fdtv
->demux
.filternum
= 16;
183 fdtv
->demux
.feednum
= 16;
184 fdtv
->demux
.start_feed
= fdtv_start_feed
;
185 fdtv
->demux
.stop_feed
= fdtv_stop_feed
;
186 fdtv
->demux
.write_to_decoder
= NULL
;
188 err
= dvb_dmx_init(&fdtv
->demux
);
190 goto fail_unreg_adapter
;
192 fdtv
->dmxdev
.filternum
= 16;
193 fdtv
->dmxdev
.demux
= &fdtv
->demux
.dmx
;
194 fdtv
->dmxdev
.capabilities
= 0;
196 err
= dvb_dmxdev_init(&fdtv
->dmxdev
, &fdtv
->adapter
);
198 goto fail_dmx_release
;
200 fdtv
->frontend
.source
= DMX_FRONTEND_0
;
202 err
= fdtv
->demux
.dmx
.add_frontend(&fdtv
->demux
.dmx
, &fdtv
->frontend
);
204 goto fail_dmxdev_release
;
206 err
= fdtv
->demux
.dmx
.connect_frontend(&fdtv
->demux
.dmx
,
209 goto fail_rem_frontend
;
211 dvb_net_init(&fdtv
->adapter
, &fdtv
->dvbnet
, &fdtv
->demux
.dmx
);
213 fdtv_frontend_init(fdtv
);
214 err
= dvb_register_frontend(&fdtv
->adapter
, &fdtv
->fe
);
216 goto fail_net_release
;
218 err
= fdtv_ca_register(fdtv
);
220 dev_info(fdtv
->device
,
221 "Conditional Access Module not enabled\n");
225 dvb_net_release(&fdtv
->dvbnet
);
226 fdtv
->demux
.dmx
.close(&fdtv
->demux
.dmx
);
228 fdtv
->demux
.dmx
.remove_frontend(&fdtv
->demux
.dmx
, &fdtv
->frontend
);
230 dvb_dmxdev_release(&fdtv
->dmxdev
);
232 dvb_dmx_release(&fdtv
->demux
);
234 dvb_unregister_adapter(&fdtv
->adapter
);
236 dev_err(fdtv
->device
, "DVB initialization failed\n");
240 void fdtv_dvb_unregister(struct firedtv
*fdtv
)
242 fdtv_ca_release(fdtv
);
243 dvb_unregister_frontend(&fdtv
->fe
);
244 dvb_net_release(&fdtv
->dvbnet
);
245 fdtv
->demux
.dmx
.close(&fdtv
->demux
.dmx
);
246 fdtv
->demux
.dmx
.remove_frontend(&fdtv
->demux
.dmx
, &fdtv
->frontend
);
247 dvb_dmxdev_release(&fdtv
->dmxdev
);
248 dvb_dmx_release(&fdtv
->demux
);
249 dvb_unregister_adapter(&fdtv
->adapter
);
252 const char *fdtv_model_names
[] = {
253 [FIREDTV_UNKNOWN
] = "unknown type",
254 [FIREDTV_DVB_S
] = "FireDTV S/CI",
255 [FIREDTV_DVB_C
] = "FireDTV C/CI",
256 [FIREDTV_DVB_T
] = "FireDTV T/CI",
257 [FIREDTV_DVB_S2
] = "FireDTV S2 ",
260 struct firedtv
*fdtv_alloc(struct device
*dev
,
261 const struct firedtv_backend
*backend
,
262 const char *name
, size_t name_len
)
264 struct firedtv
*fdtv
;
267 fdtv
= kzalloc(sizeof(*fdtv
), GFP_KERNEL
);
271 dev_set_drvdata(dev
, fdtv
);
273 fdtv
->isochannel
= -1;
274 fdtv
->voltage
= 0xff;
276 fdtv
->backend
= backend
;
278 mutex_init(&fdtv
->avc_mutex
);
279 init_waitqueue_head(&fdtv
->avc_wait
);
280 fdtv
->avc_reply_received
= true;
281 mutex_init(&fdtv
->demux_mutex
);
282 INIT_WORK(&fdtv
->remote_ctrl_work
, avc_remote_ctrl_work
);
284 for (i
= ARRAY_SIZE(fdtv_model_names
); --i
; )
285 if (strlen(fdtv_model_names
[i
]) <= name_len
&&
286 strncmp(name
, fdtv_model_names
[i
], name_len
) == 0)
293 #define MATCH_FLAGS (IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID | \
294 IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION)
296 #define DIGITAL_EVERYWHERE_OUI 0x001287
297 #define AVC_UNIT_SPEC_ID_ENTRY 0x00a02d
298 #define AVC_SW_VERSION_ENTRY 0x010001
300 static struct ieee1394_device_id fdtv_id_table
[] = {
302 /* FloppyDTV S/CI and FloppyDTV S2 */
303 .match_flags
= MATCH_FLAGS
,
304 .vendor_id
= DIGITAL_EVERYWHERE_OUI
,
305 .model_id
= 0x000024,
306 .specifier_id
= AVC_UNIT_SPEC_ID_ENTRY
,
307 .version
= AVC_SW_VERSION_ENTRY
,
310 .match_flags
= MATCH_FLAGS
,
311 .vendor_id
= DIGITAL_EVERYWHERE_OUI
,
312 .model_id
= 0x000025,
313 .specifier_id
= AVC_UNIT_SPEC_ID_ENTRY
,
314 .version
= AVC_SW_VERSION_ENTRY
,
317 .match_flags
= MATCH_FLAGS
,
318 .vendor_id
= DIGITAL_EVERYWHERE_OUI
,
319 .model_id
= 0x000026,
320 .specifier_id
= AVC_UNIT_SPEC_ID_ENTRY
,
321 .version
= AVC_SW_VERSION_ENTRY
,
323 /* FireDTV S/CI and FloppyDTV S2 */
324 .match_flags
= MATCH_FLAGS
,
325 .vendor_id
= DIGITAL_EVERYWHERE_OUI
,
326 .model_id
= 0x000034,
327 .specifier_id
= AVC_UNIT_SPEC_ID_ENTRY
,
328 .version
= AVC_SW_VERSION_ENTRY
,
331 .match_flags
= MATCH_FLAGS
,
332 .vendor_id
= DIGITAL_EVERYWHERE_OUI
,
333 .model_id
= 0x000035,
334 .specifier_id
= AVC_UNIT_SPEC_ID_ENTRY
,
335 .version
= AVC_SW_VERSION_ENTRY
,
338 .match_flags
= MATCH_FLAGS
,
339 .vendor_id
= DIGITAL_EVERYWHERE_OUI
,
340 .model_id
= 0x000036,
341 .specifier_id
= AVC_UNIT_SPEC_ID_ENTRY
,
342 .version
= AVC_SW_VERSION_ENTRY
,
345 MODULE_DEVICE_TABLE(ieee1394
, fdtv_id_table
);
347 static int __init
fdtv_init(void)
349 return fdtv_1394_init(fdtv_id_table
);
352 static void __exit
fdtv_exit(void)
357 module_init(fdtv_init
);
358 module_exit(fdtv_exit
);
360 MODULE_AUTHOR("Andreas Monitzer <andy@monitzer.com>");
361 MODULE_AUTHOR("Ben Backx <ben@bbackx.com>");
362 MODULE_DESCRIPTION("FireDTV DVB Driver");
363 MODULE_LICENSE("GPL");
364 MODULE_SUPPORTED_DEVICE("FireDTV DVB");