firedtv-dvb.c revision 87918334792a4d8a73b0511466b77bd6aa055db3
1/*
2 * FireDTV driver (formerly known as FireSAT)
3 *
4 * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
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
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>
25
26#include <dmxdev.h>
27#include <dvb_demux.h>
28#include <dvbdev.h>
29#include <dvb_frontend.h>
30
31#include "firedtv.h"
32
33static int alloc_channel(struct firedtv *fdtv)
34{
35	int i;
36
37	for (i = 0; i < 16; i++)
38		if (!__test_and_set_bit(i, &fdtv->channel_active))
39			break;
40	return i;
41}
42
43static void collect_channels(struct firedtv *fdtv, int *pidc, u16 pid[])
44{
45	int i, n;
46
47	for (i = 0, n = 0; i < 16; i++)
48		if (test_bit(i, &fdtv->channel_active))
49			pid[n++] = fdtv->channel_pid[i];
50	*pidc = n;
51}
52
53static inline void dealloc_channel(struct firedtv *fdtv, int i)
54{
55	__clear_bit(i, &fdtv->channel_active);
56}
57
58int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed)
59{
60	struct firedtv *fdtv = dvbdmxfeed->demux->priv;
61	int pidc, c, ret;
62	u16 pids[16];
63
64	switch (dvbdmxfeed->type) {
65	case DMX_TYPE_TS:
66	case DMX_TYPE_SEC:
67		break;
68	default:
69		dev_err(fdtv->device, "can't start dmx feed: invalid type %u\n",
70			dvbdmxfeed->type);
71		return -EINVAL;
72	}
73
74	if (mutex_lock_interruptible(&fdtv->demux_mutex))
75		return -EINTR;
76
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:
82		case DMX_TS_PES_PCR:
83		case DMX_TS_PES_OTHER:
84			c = alloc_channel(fdtv);
85			break;
86		default:
87			dev_err(fdtv->device,
88				"can't start dmx feed: invalid pes type %u\n",
89				dvbdmxfeed->pes_type);
90			ret = -EINVAL;
91			goto out;
92		}
93	} else {
94		c = alloc_channel(fdtv);
95	}
96
97	if (c > 15) {
98		dev_err(fdtv->device, "can't start dmx feed: busy\n");
99		ret = -EBUSY;
100		goto out;
101	}
102
103	dvbdmxfeed->priv = (typeof(dvbdmxfeed->priv))(unsigned long)c;
104	fdtv->channel_pid[c] = dvbdmxfeed->pid;
105	collect_channels(fdtv, &pidc, pids);
106
107	if (dvbdmxfeed->pid == 8192) {
108		ret = avc_tuner_get_ts(fdtv);
109		if (ret) {
110			dealloc_channel(fdtv, c);
111			dev_err(fdtv->device, "can't get TS\n");
112			goto out;
113		}
114	} else {
115		ret = avc_tuner_set_pids(fdtv, pidc, pids);
116		if (ret) {
117			dealloc_channel(fdtv, c);
118			dev_err(fdtv->device, "can't set PIDs\n");
119			goto out;
120		}
121	}
122out:
123	mutex_unlock(&fdtv->demux_mutex);
124
125	return ret;
126}
127
128int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
129{
130	struct dvb_demux *demux = dvbdmxfeed->demux;
131	struct firedtv *fdtv = demux->priv;
132	int pidc, c, ret;
133	u16 pids[16];
134
135	if (dvbdmxfeed->type == DMX_TYPE_TS &&
136	    !((dvbdmxfeed->ts_type & TS_PACKET) &&
137	      (demux->dmx.frontend->source != DMX_MEMORY_FE))) {
138
139		if (dvbdmxfeed->ts_type & TS_DECODER) {
140			if (dvbdmxfeed->pes_type >= DMX_TS_PES_OTHER ||
141			    !demux->pesfilter[dvbdmxfeed->pes_type])
142				return -EINVAL;
143
144			demux->pids[dvbdmxfeed->pes_type] |= 0x8000;
145			demux->pesfilter[dvbdmxfeed->pes_type] = NULL;
146		}
147
148		if (!(dvbdmxfeed->ts_type & TS_DECODER &&
149		      dvbdmxfeed->pes_type < DMX_TS_PES_OTHER))
150			return 0;
151	}
152
153	if (mutex_lock_interruptible(&fdtv->demux_mutex))
154		return -EINTR;
155
156	c = (unsigned long)dvbdmxfeed->priv;
157	dealloc_channel(fdtv, c);
158	collect_channels(fdtv, &pidc, pids);
159
160	ret = avc_tuner_set_pids(fdtv, pidc, pids);
161
162	mutex_unlock(&fdtv->demux_mutex);
163
164	return ret;
165}
166
167DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
168
169int fdtv_dvb_register(struct firedtv *fdtv)
170{
171	int err;
172
173	err = dvb_register_adapter(&fdtv->adapter, fdtv_model_names[fdtv->type],
174				   THIS_MODULE, fdtv->device, adapter_nr);
175	if (err < 0)
176		goto fail_log;
177
178	/*DMX_TS_FILTERING | DMX_SECTION_FILTERING*/
179	fdtv->demux.dmx.capabilities = 0;
180
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;
187
188	err = dvb_dmx_init(&fdtv->demux);
189	if (err)
190		goto fail_unreg_adapter;
191
192	fdtv->dmxdev.filternum    = 16;
193	fdtv->dmxdev.demux        = &fdtv->demux.dmx;
194	fdtv->dmxdev.capabilities = 0;
195
196	err = dvb_dmxdev_init(&fdtv->dmxdev, &fdtv->adapter);
197	if (err)
198		goto fail_dmx_release;
199
200	fdtv->frontend.source = DMX_FRONTEND_0;
201
202	err = fdtv->demux.dmx.add_frontend(&fdtv->demux.dmx, &fdtv->frontend);
203	if (err)
204		goto fail_dmxdev_release;
205
206	err = fdtv->demux.dmx.connect_frontend(&fdtv->demux.dmx,
207					       &fdtv->frontend);
208	if (err)
209		goto fail_rem_frontend;
210
211	dvb_net_init(&fdtv->adapter, &fdtv->dvbnet, &fdtv->demux.dmx);
212
213	fdtv_frontend_init(fdtv);
214	err = dvb_register_frontend(&fdtv->adapter, &fdtv->fe);
215	if (err)
216		goto fail_net_release;
217
218	err = fdtv_ca_register(fdtv);
219	if (err)
220		dev_info(fdtv->device,
221			 "Conditional Access Module not enabled\n");
222	return 0;
223
224fail_net_release:
225	dvb_net_release(&fdtv->dvbnet);
226	fdtv->demux.dmx.close(&fdtv->demux.dmx);
227fail_rem_frontend:
228	fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend);
229fail_dmxdev_release:
230	dvb_dmxdev_release(&fdtv->dmxdev);
231fail_dmx_release:
232	dvb_dmx_release(&fdtv->demux);
233fail_unreg_adapter:
234	dvb_unregister_adapter(&fdtv->adapter);
235fail_log:
236	dev_err(fdtv->device, "DVB initialization failed\n");
237	return err;
238}
239
240void fdtv_dvb_unregister(struct firedtv *fdtv)
241{
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);
250}
251
252const 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  ",
258};
259
260struct firedtv *fdtv_alloc(struct device *dev,
261			   const struct firedtv_backend *backend,
262			   const char *name, size_t name_len)
263{
264	struct firedtv *fdtv;
265	int i;
266
267	fdtv = kzalloc(sizeof(*fdtv), GFP_KERNEL);
268	if (!fdtv)
269		return NULL;
270
271	dev_set_drvdata(dev, fdtv);
272	fdtv->device		= dev;
273	fdtv->isochannel	= -1;
274	fdtv->voltage		= 0xff;
275	fdtv->tone		= 0xff;
276	fdtv->backend		= backend;
277
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);
283
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)
287			break;
288	fdtv->type = i;
289
290	return fdtv;
291}
292
293#define MATCH_FLAGS (IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID | \
294		     IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION)
295
296#define DIGITAL_EVERYWHERE_OUI	0x001287
297#define AVC_UNIT_SPEC_ID_ENTRY	0x00a02d
298#define AVC_SW_VERSION_ENTRY	0x010001
299
300const struct ieee1394_device_id fdtv_id_table[] = {
301	{
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,
308	}, {
309		/* FloppyDTV T/CI */
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,
315	}, {
316		/* FloppyDTV C/CI */
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,
322	}, {
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,
329	}, {
330		/* FireDTV T/CI */
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,
336	}, {
337		/* FireDTV C/CI */
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,
343	}, {}
344};
345MODULE_DEVICE_TABLE(ieee1394, fdtv_id_table);
346
347static int __init fdtv_init(void)
348{
349	int ret;
350
351	ret = fdtv_fw_init();
352	if (ret < 0)
353		return ret;
354
355	ret = fdtv_1394_init();
356	if (ret < 0)
357		fdtv_fw_exit();
358
359	return ret;
360}
361
362static void __exit fdtv_exit(void)
363{
364	fdtv_1394_exit();
365	fdtv_fw_exit();
366}
367
368module_init(fdtv_init);
369module_exit(fdtv_exit);
370
371MODULE_AUTHOR("Andreas Monitzer <andy@monitzer.com>");
372MODULE_AUTHOR("Ben Backx <ben@bbackx.com>");
373MODULE_DESCRIPTION("FireDTV DVB Driver");
374MODULE_LICENSE("GPL");
375MODULE_SUPPORTED_DEVICE("FireDTV DVB");
376