root/drivers/media/firewire/firedtv-dvb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. alloc_channel
  2. collect_channels
  3. dealloc_channel
  4. fdtv_start_feed
  5. fdtv_stop_feed
  6. fdtv_dvb_register
  7. fdtv_dvb_unregister

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * FireDTV driver (formerly known as FireSAT)
   4  *
   5  * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
   6  * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
   7  */
   8 
   9 #include <linux/bitops.h>
  10 #include <linux/device.h>
  11 #include <linux/errno.h>
  12 #include <linux/kernel.h>
  13 #include <linux/module.h>
  14 #include <linux/mutex.h>
  15 #include <linux/types.h>
  16 
  17 #include <media/dmxdev.h>
  18 #include <media/dvb_demux.h>
  19 #include <media/dvbdev.h>
  20 #include <media/dvb_frontend.h>
  21 
  22 #include "firedtv.h"
  23 
  24 static int alloc_channel(struct firedtv *fdtv)
  25 {
  26         int i;
  27 
  28         for (i = 0; i < 16; i++)
  29                 if (!__test_and_set_bit(i, &fdtv->channel_active))
  30                         break;
  31         return i;
  32 }
  33 
  34 static void collect_channels(struct firedtv *fdtv, int *pidc, u16 pid[])
  35 {
  36         int i, n;
  37 
  38         for (i = 0, n = 0; i < 16; i++)
  39                 if (test_bit(i, &fdtv->channel_active))
  40                         pid[n++] = fdtv->channel_pid[i];
  41         *pidc = n;
  42 }
  43 
  44 static inline void dealloc_channel(struct firedtv *fdtv, int i)
  45 {
  46         __clear_bit(i, &fdtv->channel_active);
  47 }
  48 
  49 int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed)
  50 {
  51         struct firedtv *fdtv = dvbdmxfeed->demux->priv;
  52         int pidc, c, ret;
  53         u16 pids[16];
  54 
  55         switch (dvbdmxfeed->type) {
  56         case DMX_TYPE_TS:
  57         case DMX_TYPE_SEC:
  58                 break;
  59         default:
  60                 dev_err(fdtv->device, "can't start dmx feed: invalid type %u\n",
  61                         dvbdmxfeed->type);
  62                 return -EINVAL;
  63         }
  64 
  65         if (mutex_lock_interruptible(&fdtv->demux_mutex))
  66                 return -EINTR;
  67 
  68         if (dvbdmxfeed->type == DMX_TYPE_TS) {
  69                 switch (dvbdmxfeed->pes_type) {
  70                 case DMX_PES_VIDEO:
  71                 case DMX_PES_AUDIO:
  72                 case DMX_PES_TELETEXT:
  73                 case DMX_PES_PCR:
  74                 case DMX_PES_OTHER:
  75                         c = alloc_channel(fdtv);
  76                         break;
  77                 default:
  78                         dev_err(fdtv->device,
  79                                 "can't start dmx feed: invalid pes type %u\n",
  80                                 dvbdmxfeed->pes_type);
  81                         ret = -EINVAL;
  82                         goto out;
  83                 }
  84         } else {
  85                 c = alloc_channel(fdtv);
  86         }
  87 
  88         if (c > 15) {
  89                 dev_err(fdtv->device, "can't start dmx feed: busy\n");
  90                 ret = -EBUSY;
  91                 goto out;
  92         }
  93 
  94         dvbdmxfeed->priv = (typeof(dvbdmxfeed->priv))(unsigned long)c;
  95         fdtv->channel_pid[c] = dvbdmxfeed->pid;
  96         collect_channels(fdtv, &pidc, pids);
  97 
  98         if (dvbdmxfeed->pid == 8192) {
  99                 ret = avc_tuner_get_ts(fdtv);
 100                 if (ret) {
 101                         dealloc_channel(fdtv, c);
 102                         dev_err(fdtv->device, "can't get TS\n");
 103                         goto out;
 104                 }
 105         } else {
 106                 ret = avc_tuner_set_pids(fdtv, pidc, pids);
 107                 if (ret) {
 108                         dealloc_channel(fdtv, c);
 109                         dev_err(fdtv->device, "can't set PIDs\n");
 110                         goto out;
 111                 }
 112         }
 113 out:
 114         mutex_unlock(&fdtv->demux_mutex);
 115 
 116         return ret;
 117 }
 118 
 119 int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
 120 {
 121         struct dvb_demux *demux = dvbdmxfeed->demux;
 122         struct firedtv *fdtv = demux->priv;
 123         int pidc, c, ret;
 124         u16 pids[16];
 125 
 126         if (dvbdmxfeed->type == DMX_TYPE_TS &&
 127             !((dvbdmxfeed->ts_type & TS_PACKET) &&
 128               (demux->dmx.frontend->source != DMX_MEMORY_FE))) {
 129 
 130                 if (dvbdmxfeed->ts_type & TS_DECODER) {
 131                         if (dvbdmxfeed->pes_type >= DMX_PES_OTHER ||
 132                             !demux->pesfilter[dvbdmxfeed->pes_type])
 133                                 return -EINVAL;
 134 
 135                         demux->pids[dvbdmxfeed->pes_type] |= 0x8000;
 136                         demux->pesfilter[dvbdmxfeed->pes_type] = NULL;
 137                 }
 138 
 139                 if (!(dvbdmxfeed->ts_type & TS_DECODER &&
 140                       dvbdmxfeed->pes_type < DMX_PES_OTHER))
 141                         return 0;
 142         }
 143 
 144         if (mutex_lock_interruptible(&fdtv->demux_mutex))
 145                 return -EINTR;
 146 
 147         c = (unsigned long)dvbdmxfeed->priv;
 148         dealloc_channel(fdtv, c);
 149         collect_channels(fdtv, &pidc, pids);
 150 
 151         ret = avc_tuner_set_pids(fdtv, pidc, pids);
 152 
 153         mutex_unlock(&fdtv->demux_mutex);
 154 
 155         return ret;
 156 }
 157 
 158 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 159 
 160 int fdtv_dvb_register(struct firedtv *fdtv, const char *name)
 161 {
 162         int err;
 163 
 164         err = dvb_register_adapter(&fdtv->adapter, name,
 165                                    THIS_MODULE, fdtv->device, adapter_nr);
 166         if (err < 0)
 167                 goto fail_log;
 168 
 169         /*DMX_TS_FILTERING | DMX_SECTION_FILTERING*/
 170         fdtv->demux.dmx.capabilities = 0;
 171 
 172         fdtv->demux.priv        = fdtv;
 173         fdtv->demux.filternum   = 16;
 174         fdtv->demux.feednum     = 16;
 175         fdtv->demux.start_feed  = fdtv_start_feed;
 176         fdtv->demux.stop_feed   = fdtv_stop_feed;
 177         fdtv->demux.write_to_decoder = NULL;
 178 
 179         err = dvb_dmx_init(&fdtv->demux);
 180         if (err)
 181                 goto fail_unreg_adapter;
 182 
 183         fdtv->dmxdev.filternum    = 16;
 184         fdtv->dmxdev.demux        = &fdtv->demux.dmx;
 185         fdtv->dmxdev.capabilities = 0;
 186 
 187         err = dvb_dmxdev_init(&fdtv->dmxdev, &fdtv->adapter);
 188         if (err)
 189                 goto fail_dmx_release;
 190 
 191         fdtv->frontend.source = DMX_FRONTEND_0;
 192 
 193         err = fdtv->demux.dmx.add_frontend(&fdtv->demux.dmx, &fdtv->frontend);
 194         if (err)
 195                 goto fail_dmxdev_release;
 196 
 197         err = fdtv->demux.dmx.connect_frontend(&fdtv->demux.dmx,
 198                                                &fdtv->frontend);
 199         if (err)
 200                 goto fail_rem_frontend;
 201 
 202         err = dvb_net_init(&fdtv->adapter, &fdtv->dvbnet, &fdtv->demux.dmx);
 203         if (err)
 204                 goto fail_disconnect_frontend;
 205 
 206         fdtv_frontend_init(fdtv, name);
 207         err = dvb_register_frontend(&fdtv->adapter, &fdtv->fe);
 208         if (err)
 209                 goto fail_net_release;
 210 
 211         err = fdtv_ca_register(fdtv);
 212         if (err)
 213                 dev_info(fdtv->device,
 214                          "Conditional Access Module not enabled\n");
 215         return 0;
 216 
 217 fail_net_release:
 218         dvb_net_release(&fdtv->dvbnet);
 219 fail_disconnect_frontend:
 220         fdtv->demux.dmx.close(&fdtv->demux.dmx);
 221 fail_rem_frontend:
 222         fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend);
 223 fail_dmxdev_release:
 224         dvb_dmxdev_release(&fdtv->dmxdev);
 225 fail_dmx_release:
 226         dvb_dmx_release(&fdtv->demux);
 227 fail_unreg_adapter:
 228         dvb_unregister_adapter(&fdtv->adapter);
 229 fail_log:
 230         dev_err(fdtv->device, "DVB initialization failed\n");
 231         return err;
 232 }
 233 
 234 void fdtv_dvb_unregister(struct firedtv *fdtv)
 235 {
 236         fdtv_ca_release(fdtv);
 237         dvb_unregister_frontend(&fdtv->fe);
 238         dvb_net_release(&fdtv->dvbnet);
 239         fdtv->demux.dmx.close(&fdtv->demux.dmx);
 240         fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend);
 241         dvb_dmxdev_release(&fdtv->dmxdev);
 242         dvb_dmx_release(&fdtv->demux);
 243         dvb_unregister_adapter(&fdtv->adapter);
 244 }

/* [<][>][^][v][top][bottom][index][help] */