0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/bitops.h>
0010 #include <linux/device.h>
0011 #include <linux/errno.h>
0012 #include <linux/kernel.h>
0013 #include <linux/module.h>
0014 #include <linux/mutex.h>
0015 #include <linux/types.h>
0016
0017 #include <media/dmxdev.h>
0018 #include <media/dvb_demux.h>
0019 #include <media/dvbdev.h>
0020 #include <media/dvb_frontend.h>
0021
0022 #include "firedtv.h"
0023
0024 static int alloc_channel(struct firedtv *fdtv)
0025 {
0026 int i;
0027
0028 for (i = 0; i < 16; i++)
0029 if (!__test_and_set_bit(i, &fdtv->channel_active))
0030 break;
0031 return i;
0032 }
0033
0034 static void collect_channels(struct firedtv *fdtv, int *pidc, u16 pid[])
0035 {
0036 int i, n;
0037
0038 for (i = 0, n = 0; i < 16; i++)
0039 if (test_bit(i, &fdtv->channel_active))
0040 pid[n++] = fdtv->channel_pid[i];
0041 *pidc = n;
0042 }
0043
0044 static inline void dealloc_channel(struct firedtv *fdtv, int i)
0045 {
0046 __clear_bit(i, &fdtv->channel_active);
0047 }
0048
0049 int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed)
0050 {
0051 struct firedtv *fdtv = dvbdmxfeed->demux->priv;
0052 int pidc, c, ret;
0053 u16 pids[16];
0054
0055 switch (dvbdmxfeed->type) {
0056 case DMX_TYPE_TS:
0057 case DMX_TYPE_SEC:
0058 break;
0059 default:
0060 dev_err(fdtv->device, "can't start dmx feed: invalid type %u\n",
0061 dvbdmxfeed->type);
0062 return -EINVAL;
0063 }
0064
0065 if (mutex_lock_interruptible(&fdtv->demux_mutex))
0066 return -EINTR;
0067
0068 if (dvbdmxfeed->type == DMX_TYPE_TS) {
0069 switch (dvbdmxfeed->pes_type) {
0070 case DMX_PES_VIDEO:
0071 case DMX_PES_AUDIO:
0072 case DMX_PES_TELETEXT:
0073 case DMX_PES_PCR:
0074 case DMX_PES_OTHER:
0075 c = alloc_channel(fdtv);
0076 break;
0077 default:
0078 dev_err(fdtv->device,
0079 "can't start dmx feed: invalid pes type %u\n",
0080 dvbdmxfeed->pes_type);
0081 ret = -EINVAL;
0082 goto out;
0083 }
0084 } else {
0085 c = alloc_channel(fdtv);
0086 }
0087
0088 if (c > 15) {
0089 dev_err(fdtv->device, "can't start dmx feed: busy\n");
0090 ret = -EBUSY;
0091 goto out;
0092 }
0093
0094 dvbdmxfeed->priv = (typeof(dvbdmxfeed->priv))(unsigned long)c;
0095 fdtv->channel_pid[c] = dvbdmxfeed->pid;
0096 collect_channels(fdtv, &pidc, pids);
0097
0098 if (dvbdmxfeed->pid == 8192) {
0099 ret = avc_tuner_get_ts(fdtv);
0100 if (ret) {
0101 dealloc_channel(fdtv, c);
0102 dev_err(fdtv->device, "can't get TS\n");
0103 goto out;
0104 }
0105 } else {
0106 ret = avc_tuner_set_pids(fdtv, pidc, pids);
0107 if (ret) {
0108 dealloc_channel(fdtv, c);
0109 dev_err(fdtv->device, "can't set PIDs\n");
0110 goto out;
0111 }
0112 }
0113 out:
0114 mutex_unlock(&fdtv->demux_mutex);
0115
0116 return ret;
0117 }
0118
0119 int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
0120 {
0121 struct dvb_demux *demux = dvbdmxfeed->demux;
0122 struct firedtv *fdtv = demux->priv;
0123 int pidc, c, ret;
0124 u16 pids[16];
0125
0126 if (dvbdmxfeed->type == DMX_TYPE_TS &&
0127 !((dvbdmxfeed->ts_type & TS_PACKET) &&
0128 (demux->dmx.frontend->source != DMX_MEMORY_FE))) {
0129
0130 if (dvbdmxfeed->ts_type & TS_DECODER) {
0131 if (dvbdmxfeed->pes_type >= DMX_PES_OTHER ||
0132 !demux->pesfilter[dvbdmxfeed->pes_type])
0133 return -EINVAL;
0134
0135 demux->pids[dvbdmxfeed->pes_type] |= 0x8000;
0136 demux->pesfilter[dvbdmxfeed->pes_type] = NULL;
0137 }
0138
0139 if (!(dvbdmxfeed->ts_type & TS_DECODER &&
0140 dvbdmxfeed->pes_type < DMX_PES_OTHER))
0141 return 0;
0142 }
0143
0144 if (mutex_lock_interruptible(&fdtv->demux_mutex))
0145 return -EINTR;
0146
0147 c = (unsigned long)dvbdmxfeed->priv;
0148 dealloc_channel(fdtv, c);
0149 collect_channels(fdtv, &pidc, pids);
0150
0151 ret = avc_tuner_set_pids(fdtv, pidc, pids);
0152
0153 mutex_unlock(&fdtv->demux_mutex);
0154
0155 return ret;
0156 }
0157
0158 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
0159
0160 int fdtv_dvb_register(struct firedtv *fdtv, const char *name)
0161 {
0162 int err;
0163
0164 err = dvb_register_adapter(&fdtv->adapter, name,
0165 THIS_MODULE, fdtv->device, adapter_nr);
0166 if (err < 0)
0167 goto fail_log;
0168
0169
0170 fdtv->demux.dmx.capabilities = 0;
0171
0172 fdtv->demux.priv = fdtv;
0173 fdtv->demux.filternum = 16;
0174 fdtv->demux.feednum = 16;
0175 fdtv->demux.start_feed = fdtv_start_feed;
0176 fdtv->demux.stop_feed = fdtv_stop_feed;
0177 fdtv->demux.write_to_decoder = NULL;
0178
0179 err = dvb_dmx_init(&fdtv->demux);
0180 if (err)
0181 goto fail_unreg_adapter;
0182
0183 fdtv->dmxdev.filternum = 16;
0184 fdtv->dmxdev.demux = &fdtv->demux.dmx;
0185 fdtv->dmxdev.capabilities = 0;
0186
0187 err = dvb_dmxdev_init(&fdtv->dmxdev, &fdtv->adapter);
0188 if (err)
0189 goto fail_dmx_release;
0190
0191 fdtv->frontend.source = DMX_FRONTEND_0;
0192
0193 err = fdtv->demux.dmx.add_frontend(&fdtv->demux.dmx, &fdtv->frontend);
0194 if (err)
0195 goto fail_dmxdev_release;
0196
0197 err = fdtv->demux.dmx.connect_frontend(&fdtv->demux.dmx,
0198 &fdtv->frontend);
0199 if (err)
0200 goto fail_rem_frontend;
0201
0202 err = dvb_net_init(&fdtv->adapter, &fdtv->dvbnet, &fdtv->demux.dmx);
0203 if (err)
0204 goto fail_disconnect_frontend;
0205
0206 fdtv_frontend_init(fdtv, name);
0207 err = dvb_register_frontend(&fdtv->adapter, &fdtv->fe);
0208 if (err)
0209 goto fail_net_release;
0210
0211 err = fdtv_ca_register(fdtv);
0212 if (err)
0213 dev_info(fdtv->device,
0214 "Conditional Access Module not enabled\n");
0215 return 0;
0216
0217 fail_net_release:
0218 dvb_net_release(&fdtv->dvbnet);
0219 fail_disconnect_frontend:
0220 fdtv->demux.dmx.close(&fdtv->demux.dmx);
0221 fail_rem_frontend:
0222 fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend);
0223 fail_dmxdev_release:
0224 dvb_dmxdev_release(&fdtv->dmxdev);
0225 fail_dmx_release:
0226 dvb_dmx_release(&fdtv->demux);
0227 fail_unreg_adapter:
0228 dvb_unregister_adapter(&fdtv->adapter);
0229 fail_log:
0230 dev_err(fdtv->device, "DVB initialization failed\n");
0231 return err;
0232 }
0233
0234 void fdtv_dvb_unregister(struct firedtv *fdtv)
0235 {
0236 fdtv_ca_release(fdtv);
0237 dvb_unregister_frontend(&fdtv->fe);
0238 dvb_net_release(&fdtv->dvbnet);
0239 fdtv->demux.dmx.close(&fdtv->demux.dmx);
0240 fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend);
0241 dvb_dmxdev_release(&fdtv->dmxdev);
0242 dvb_dmx_release(&fdtv->demux);
0243 dvb_unregister_adapter(&fdtv->adapter);
0244 }