cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dvb-usb-dvb.c (9490B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* dvb-usb-dvb.c is part of the DVB USB library.
      3 *
      4 * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de)
      5 * see dvb-usb-init.c for copyright information.
      6 *
      7 * This file contains functions for initializing and handling the
      8 * linux-dvb API.
      9 */
     10#include "dvb-usb-common.h"
     11#include <media/media-device.h>
     12
     13/* does the complete input transfer handling */
     14static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
     15{
     16	struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv;
     17	int newfeedcount, ret;
     18
     19	if (adap == NULL)
     20		return -ENODEV;
     21
     22	if ((adap->active_fe < 0) ||
     23	    (adap->active_fe >= adap->num_frontends_initialized)) {
     24		return -EINVAL;
     25	}
     26
     27	newfeedcount = adap->feedcount + (onoff ? 1 : -1);
     28
     29	/* stop feed before setting a new pid if there will be no pid anymore */
     30	if (newfeedcount == 0) {
     31		deb_ts("stop feeding\n");
     32		usb_urb_kill(&adap->fe_adap[adap->active_fe].stream);
     33
     34		if (adap->props.fe[adap->active_fe].streaming_ctrl != NULL) {
     35			ret = adap->props.fe[adap->active_fe].streaming_ctrl(adap, 0);
     36			if (ret < 0) {
     37				err("error while stopping stream.");
     38				return ret;
     39			}
     40		}
     41	}
     42
     43	adap->feedcount = newfeedcount;
     44
     45	/* activate the pid on the device specific pid_filter */
     46	deb_ts("setting pid (%s): %5d %04x at index %d '%s'\n",
     47		adap->fe_adap[adap->active_fe].pid_filtering ?
     48		"yes" : "no", dvbdmxfeed->pid, dvbdmxfeed->pid,
     49		dvbdmxfeed->index, onoff ? "on" : "off");
     50	if (adap->props.fe[adap->active_fe].caps & DVB_USB_ADAP_HAS_PID_FILTER &&
     51		adap->fe_adap[adap->active_fe].pid_filtering &&
     52		adap->props.fe[adap->active_fe].pid_filter != NULL)
     53		adap->props.fe[adap->active_fe].pid_filter(adap, dvbdmxfeed->index, dvbdmxfeed->pid, onoff);
     54
     55	/* start the feed if this was the first feed and there is still a feed
     56	 * for reception.
     57	 */
     58	if (adap->feedcount == onoff && adap->feedcount > 0) {
     59		deb_ts("controlling pid parser\n");
     60		if (adap->props.fe[adap->active_fe].caps & DVB_USB_ADAP_HAS_PID_FILTER &&
     61			adap->props.fe[adap->active_fe].caps &
     62			DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF &&
     63			adap->props.fe[adap->active_fe].pid_filter_ctrl != NULL) {
     64			ret = adap->props.fe[adap->active_fe].pid_filter_ctrl(adap,
     65				adap->fe_adap[adap->active_fe].pid_filtering);
     66			if (ret < 0) {
     67				err("could not handle pid_parser");
     68				return ret;
     69			}
     70		}
     71		deb_ts("start feeding\n");
     72		if (adap->props.fe[adap->active_fe].streaming_ctrl != NULL) {
     73			ret = adap->props.fe[adap->active_fe].streaming_ctrl(adap, 1);
     74			if (ret < 0) {
     75				err("error while enabling fifo.");
     76				return ret;
     77			}
     78		}
     79
     80		deb_ts("submitting all URBs\n");
     81		usb_urb_submit(&adap->fe_adap[adap->active_fe].stream);
     82	}
     83	return 0;
     84}
     85
     86static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
     87{
     88	deb_ts("start pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid,
     89	       dvbdmxfeed->type);
     90	return dvb_usb_ctrl_feed(dvbdmxfeed, 1);
     91}
     92
     93static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
     94{
     95	deb_ts("stop pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid, dvbdmxfeed->type);
     96	return dvb_usb_ctrl_feed(dvbdmxfeed, 0);
     97}
     98
     99static int dvb_usb_media_device_init(struct dvb_usb_adapter *adap)
    100{
    101#ifdef CONFIG_MEDIA_CONTROLLER_DVB
    102	struct media_device *mdev;
    103	struct dvb_usb_device *d = adap->dev;
    104	struct usb_device *udev = d->udev;
    105
    106	mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
    107	if (!mdev)
    108		return -ENOMEM;
    109
    110	media_device_usb_init(mdev, udev, d->desc->name);
    111
    112	dvb_register_media_controller(&adap->dvb_adap, mdev);
    113
    114	dev_info(&d->udev->dev, "media controller created\n");
    115#endif
    116	return 0;
    117}
    118
    119static int  dvb_usb_media_device_register(struct dvb_usb_adapter *adap)
    120{
    121#ifdef CONFIG_MEDIA_CONTROLLER_DVB
    122	return media_device_register(adap->dvb_adap.mdev);
    123#else
    124	return 0;
    125#endif
    126}
    127
    128static void dvb_usb_media_device_unregister(struct dvb_usb_adapter *adap)
    129{
    130#ifdef CONFIG_MEDIA_CONTROLLER_DVB
    131	if (!adap->dvb_adap.mdev)
    132		return;
    133
    134	mutex_lock(&adap->dvb_adap.mdev_lock);
    135
    136	media_device_unregister(adap->dvb_adap.mdev);
    137	media_device_cleanup(adap->dvb_adap.mdev);
    138	kfree(adap->dvb_adap.mdev);
    139	adap->dvb_adap.mdev = NULL;
    140
    141	mutex_unlock(&adap->dvb_adap.mdev_lock);
    142#endif
    143}
    144
    145int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums)
    146{
    147	int i;
    148	int ret = dvb_register_adapter(&adap->dvb_adap, adap->dev->desc->name,
    149				       adap->dev->owner, &adap->dev->udev->dev,
    150				       adapter_nums);
    151
    152	if (ret < 0) {
    153		deb_info("dvb_register_adapter failed: error %d", ret);
    154		goto err;
    155	}
    156	adap->dvb_adap.priv = adap;
    157
    158	ret = dvb_usb_media_device_init(adap);
    159	if (ret < 0) {
    160		deb_info("dvb_usb_media_device_init failed: error %d", ret);
    161		goto err_mc;
    162	}
    163
    164	if (adap->dev->props.read_mac_address) {
    165		if (adap->dev->props.read_mac_address(adap->dev, adap->dvb_adap.proposed_mac) == 0)
    166			info("MAC address: %pM", adap->dvb_adap.proposed_mac);
    167		else
    168			err("MAC address reading failed.");
    169	}
    170
    171
    172	adap->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
    173	adap->demux.priv             = adap;
    174
    175	adap->demux.filternum        = 0;
    176	for (i = 0; i < adap->props.num_frontends; i++) {
    177		if (adap->demux.filternum < adap->fe_adap[i].max_feed_count)
    178			adap->demux.filternum = adap->fe_adap[i].max_feed_count;
    179	}
    180	adap->demux.feednum          = adap->demux.filternum;
    181	adap->demux.start_feed       = dvb_usb_start_feed;
    182	adap->demux.stop_feed        = dvb_usb_stop_feed;
    183	adap->demux.write_to_decoder = NULL;
    184	if ((ret = dvb_dmx_init(&adap->demux)) < 0) {
    185		err("dvb_dmx_init failed: error %d", ret);
    186		goto err_dmx;
    187	}
    188
    189	adap->dmxdev.filternum       = adap->demux.filternum;
    190	adap->dmxdev.demux           = &adap->demux.dmx;
    191	adap->dmxdev.capabilities    = 0;
    192	if ((ret = dvb_dmxdev_init(&adap->dmxdev, &adap->dvb_adap)) < 0) {
    193		err("dvb_dmxdev_init failed: error %d", ret);
    194		goto err_dmx_dev;
    195	}
    196
    197	if ((ret = dvb_net_init(&adap->dvb_adap, &adap->dvb_net,
    198						&adap->demux.dmx)) < 0) {
    199		err("dvb_net_init failed: error %d", ret);
    200		goto err_net_init;
    201	}
    202
    203	adap->state |= DVB_USB_ADAP_STATE_DVB;
    204	return 0;
    205
    206err_net_init:
    207	dvb_dmxdev_release(&adap->dmxdev);
    208err_dmx_dev:
    209	dvb_dmx_release(&adap->demux);
    210err_dmx:
    211	dvb_usb_media_device_unregister(adap);
    212err_mc:
    213	dvb_unregister_adapter(&adap->dvb_adap);
    214err:
    215	return ret;
    216}
    217
    218int dvb_usb_adapter_dvb_exit(struct dvb_usb_adapter *adap)
    219{
    220	if (adap->state & DVB_USB_ADAP_STATE_DVB) {
    221		deb_info("unregistering DVB part\n");
    222		dvb_net_release(&adap->dvb_net);
    223		adap->demux.dmx.close(&adap->demux.dmx);
    224		dvb_dmxdev_release(&adap->dmxdev);
    225		dvb_dmx_release(&adap->demux);
    226		dvb_usb_media_device_unregister(adap);
    227		dvb_unregister_adapter(&adap->dvb_adap);
    228		adap->state &= ~DVB_USB_ADAP_STATE_DVB;
    229	}
    230	return 0;
    231}
    232
    233static int dvb_usb_set_active_fe(struct dvb_frontend *fe, int onoff)
    234{
    235	struct dvb_usb_adapter *adap = fe->dvb->priv;
    236
    237	int ret = (adap->props.frontend_ctrl) ?
    238		adap->props.frontend_ctrl(fe, onoff) : 0;
    239
    240	if (ret < 0) {
    241		err("frontend_ctrl request failed");
    242		return ret;
    243	}
    244	if (onoff)
    245		adap->active_fe = fe->id;
    246
    247	return 0;
    248}
    249
    250static int dvb_usb_fe_wakeup(struct dvb_frontend *fe)
    251{
    252	struct dvb_usb_adapter *adap = fe->dvb->priv;
    253
    254	dvb_usb_device_power_ctrl(adap->dev, 1);
    255
    256	dvb_usb_set_active_fe(fe, 1);
    257
    258	if (adap->fe_adap[fe->id].fe_init)
    259		adap->fe_adap[fe->id].fe_init(fe);
    260
    261	return 0;
    262}
    263
    264static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
    265{
    266	struct dvb_usb_adapter *adap = fe->dvb->priv;
    267
    268	if (adap->fe_adap[fe->id].fe_sleep)
    269		adap->fe_adap[fe->id].fe_sleep(fe);
    270
    271	dvb_usb_set_active_fe(fe, 0);
    272
    273	return dvb_usb_device_power_ctrl(adap->dev, 0);
    274}
    275
    276int dvb_usb_adapter_frontend_init(struct dvb_usb_adapter *adap)
    277{
    278	int ret, i;
    279
    280	/* register all given adapter frontends */
    281	for (i = 0; i < adap->props.num_frontends; i++) {
    282
    283		if (adap->props.fe[i].frontend_attach == NULL) {
    284			err("strange: '%s' #%d,%d doesn't want to attach a frontend.",
    285			    adap->dev->desc->name, adap->id, i);
    286
    287			return 0;
    288		}
    289
    290		ret = adap->props.fe[i].frontend_attach(adap);
    291		if (ret || adap->fe_adap[i].fe == NULL) {
    292			/* only print error when there is no FE at all */
    293			if (i == 0)
    294				err("no frontend was attached by '%s'",
    295					adap->dev->desc->name);
    296
    297			return 0;
    298		}
    299
    300		adap->fe_adap[i].fe->id = i;
    301
    302		/* re-assign sleep and wakeup functions */
    303		adap->fe_adap[i].fe_init = adap->fe_adap[i].fe->ops.init;
    304		adap->fe_adap[i].fe->ops.init  = dvb_usb_fe_wakeup;
    305		adap->fe_adap[i].fe_sleep = adap->fe_adap[i].fe->ops.sleep;
    306		adap->fe_adap[i].fe->ops.sleep = dvb_usb_fe_sleep;
    307
    308		if (dvb_register_frontend(&adap->dvb_adap, adap->fe_adap[i].fe)) {
    309			err("Frontend %d registration failed.", i);
    310			dvb_frontend_detach(adap->fe_adap[i].fe);
    311			adap->fe_adap[i].fe = NULL;
    312			/* In error case, do not try register more FEs,
    313			 * still leaving already registered FEs alive. */
    314			if (i == 0)
    315				return -ENODEV;
    316			else
    317				return 0;
    318		}
    319
    320		/* only attach the tuner if the demod is there */
    321		if (adap->props.fe[i].tuner_attach != NULL)
    322			adap->props.fe[i].tuner_attach(adap);
    323
    324		adap->num_frontends_initialized++;
    325	}
    326
    327	ret = dvb_create_media_graph(&adap->dvb_adap, true);
    328	if (ret)
    329		return ret;
    330
    331	ret = dvb_usb_media_device_register(adap);
    332
    333	return ret;
    334}
    335
    336int dvb_usb_adapter_frontend_exit(struct dvb_usb_adapter *adap)
    337{
    338	int i = adap->num_frontends_initialized - 1;
    339
    340	/* unregister all given adapter frontends */
    341	for (; i >= 0; i--) {
    342		if (adap->fe_adap[i].fe != NULL) {
    343			dvb_unregister_frontend(adap->fe_adap[i].fe);
    344			dvb_frontend_detach(adap->fe_adap[i].fe);
    345		}
    346	}
    347	adap->num_frontends_initialized = 0;
    348
    349	return 0;
    350}