dvb_usb_dvb.c 10.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
/* dvb-usb-dvb.c is part of the DVB USB library.
 *
 * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
 * see dvb-usb-init.c for copyright information.
 *
 * This file contains functions for initializing and handling the
 * linux-dvb API.
 */
#include "dvb_usb_common.h"

11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
static void dvb_usb_data_complete(struct usb_data_stream *stream, u8 *buffer,
		size_t length)
{
	struct dvb_usb_adapter *adap = stream->user_priv;
	if (adap->feedcount > 0 && adap->state & DVB_USB_ADAP_STATE_DVB)
		dvb_dmx_swfilter(&adap->demux, buffer, length);
}

static void dvb_usb_data_complete_204(struct usb_data_stream *stream,
		u8 *buffer, size_t length)
{
	struct dvb_usb_adapter *adap = stream->user_priv;
	if (adap->feedcount > 0 && adap->state & DVB_USB_ADAP_STATE_DVB)
		dvb_dmx_swfilter_204(&adap->demux, buffer, length);
}

static void dvb_usb_data_complete_raw(struct usb_data_stream *stream,
				      u8 *buffer, size_t length)
{
	struct dvb_usb_adapter *adap = stream->user_priv;
	if (adap->feedcount > 0 && adap->state & DVB_USB_ADAP_STATE_DVB)
		dvb_dmx_swfilter_raw(&adap->demux, buffer, length);
}

int dvb_usb_adapter_stream_init(struct dvb_usb_adapter *adap)
{
	int ret;
	struct usb_data_stream_properties stream_props;

	adap->stream.udev = adap->dev->udev;
	adap->stream.user_priv = adap;

	/* resolve USB stream configuration for buffer alloc */
	if (adap->dev->props.get_usb_stream_config) {
		ret = adap->dev->props.get_usb_stream_config(NULL,
				&stream_props);
		if (ret < 0)
			return ret;
	} else {
50
		stream_props = adap->props.stream;
51 52 53 54 55 56 57 58 59 60 61 62 63 64
	}

	/* FIXME: can be removed as set later in anyway */
	adap->stream.complete = dvb_usb_data_complete;

	return usb_urb_init(&adap->stream, &stream_props);
}

int dvb_usb_adapter_stream_exit(struct dvb_usb_adapter *adap)
{
	usb_urb_exit(&adap->stream);
	return 0;
}

65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
/* does the complete input transfer handling */
static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
{
	struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv;
	int newfeedcount, ret;

	if (adap == NULL)
		return -ENODEV;

	if ((adap->active_fe < 0) ||
	    (adap->active_fe >= adap->num_frontends_initialized)) {
		return -EINVAL;
	}

	newfeedcount = adap->feedcount + (onoff ? 1 : -1);

	/* stop feed before setting a new pid if there will be no pid anymore */
	if (newfeedcount == 0) {
		deb_ts("stop feeding\n");
84
		usb_urb_kill(&adap->stream);
85 86

		if (adap->props.fe[adap->active_fe].streaming_ctrl != NULL) {
87 88
			ret = adap->props.fe[adap->active_fe].streaming_ctrl(
				adap, 0);
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
			if (ret < 0) {
				err("error while stopping stream.");
				return ret;
			}
		}
	}

	adap->feedcount = newfeedcount;

	/* activate the pid on the device specific pid_filter */
	deb_ts("setting pid (%s): %5d %04x at index %d '%s'\n",
		adap->fe_adap[adap->active_fe].pid_filtering ?
		"yes" : "no", dvbdmxfeed->pid, dvbdmxfeed->pid,
		dvbdmxfeed->index, onoff ? "on" : "off");
	if (adap->props.fe[adap->active_fe].caps & DVB_USB_ADAP_HAS_PID_FILTER &&
		adap->fe_adap[adap->active_fe].pid_filtering &&
		adap->props.fe[adap->active_fe].pid_filter != NULL)
106 107
		adap->props.fe[adap->active_fe].pid_filter(adap,
			dvbdmxfeed->index, dvbdmxfeed->pid, onoff);
108 109 110 111 112

	/* start the feed if this was the first feed and there is still a feed
	 * for reception.
	 */
	if (adap->feedcount == onoff && adap->feedcount > 0) {
113
		struct usb_data_stream_properties stream_props;
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
		unsigned int ts_props;

		/* resolve TS configuration */
		if (adap->dev->props.get_ts_config) {
			ret = adap->dev->props.get_ts_config(
					adap->fe_adap[adap->active_fe].fe,
					&ts_props);
			if (ret < 0)
				return ret;
		} else {
			ts_props = 0; /* normal 188 payload only TS */
		}

		if (ts_props & DVB_USB_ADAP_RECEIVES_204_BYTE_TS)
			adap->stream.complete = dvb_usb_data_complete_204;
		else if (ts_props & DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD)
			adap->stream.complete = dvb_usb_data_complete_raw;
		else
			adap->stream.complete = dvb_usb_data_complete;
133 134 135 136 137 138 139 140 141

		/* resolve USB stream configuration */
		if (adap->dev->props.get_usb_stream_config) {
			ret = adap->dev->props.get_usb_stream_config(
					adap->fe_adap[adap->active_fe].fe,
					&stream_props);
			if (ret < 0)
				return ret;
		} else {
142
			stream_props = adap->props.stream;
143 144
		}

145
		deb_ts("submitting all URBs\n");
146
		usb_urb_submit(&adap->stream, &stream_props);
147 148 149 150 151 152

		deb_ts("controlling pid parser\n");
		if (adap->props.fe[adap->active_fe].caps & DVB_USB_ADAP_HAS_PID_FILTER &&
			adap->props.fe[adap->active_fe].caps &
			DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF &&
			adap->props.fe[adap->active_fe].pid_filter_ctrl != NULL) {
153 154
			ret = adap->props.fe[adap->active_fe].pid_filter_ctrl(
				adap,
155 156 157 158 159 160 161 162
				adap->fe_adap[adap->active_fe].pid_filtering);
			if (ret < 0) {
				err("could not handle pid_parser");
				return ret;
			}
		}
		deb_ts("start feeding\n");
		if (adap->props.fe[adap->active_fe].streaming_ctrl != NULL) {
163 164
			ret = adap->props.fe[adap->active_fe].streaming_ctrl(
				adap, 1);
165 166 167 168 169 170 171 172 173 174 175 176
			if (ret < 0) {
				err("error while enabling fifo.");
				return ret;
			}
		}

	}
	return 0;
}

static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
{
177 178 179
	deb_ts("start pid: 0x%04x, feedtype: %d\n",
		dvbdmxfeed->pid, dvbdmxfeed->type);
	return dvb_usb_ctrl_feed(dvbdmxfeed, 1);
180 181 182 183
}

static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
{
184 185 186
	deb_ts("stop pid: 0x%04x, feedtype: %d\n",
			dvbdmxfeed->pid, dvbdmxfeed->type);
	return dvb_usb_ctrl_feed(dvbdmxfeed, 0);
187 188
}

189
int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap)
190 191
{
	int i;
192
	int ret = dvb_register_adapter(&adap->dvb_adap, adap->dev->name,
193 194
				       adap->dev->props.owner,
				       &adap->dev->udev->dev,
195
				       adap->dev->props.adapter_nr);
196 197 198 199 200 201 202 203
	if (ret < 0) {
		deb_info("dvb_register_adapter failed: error %d", ret);
		goto err;
	}
	adap->dvb_adap.priv = adap;
	adap->dvb_adap.fe_ioctl_override = adap->props.fe_ioctl_override;

	if (adap->dev->props.read_mac_address) {
204 205 206
		if (adap->dev->props.read_mac_address(adap->dev,
				adap->dvb_adap.proposed_mac) == 0)
			info("MAC address: %pM", adap->dvb_adap.proposed_mac);
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
		else
			err("MAC address reading failed.");
	}


	adap->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
	adap->demux.priv             = adap;

	adap->demux.filternum        = 0;
	for (i = 0; i < adap->props.num_frontends; i++) {
		if (adap->demux.filternum < adap->fe_adap[i].max_feed_count)
			adap->demux.filternum = adap->fe_adap[i].max_feed_count;
	}
	adap->demux.feednum          = adap->demux.filternum;
	adap->demux.start_feed       = dvb_usb_start_feed;
	adap->demux.stop_feed        = dvb_usb_stop_feed;
	adap->demux.write_to_decoder = NULL;
224 225 226
	ret = dvb_dmx_init(&adap->demux);
	if (ret < 0) {
		err("dvb_dmx_init failed: error %d", ret);
227 228 229 230 231 232
		goto err_dmx;
	}

	adap->dmxdev.filternum       = adap->demux.filternum;
	adap->dmxdev.demux           = &adap->demux.dmx;
	adap->dmxdev.capabilities    = 0;
233 234 235
	ret = dvb_dmxdev_init(&adap->dmxdev, &adap->dvb_adap);
	if (ret < 0) {
		err("dvb_dmxdev_init failed: error %d", ret);
236 237 238
		goto err_dmx_dev;
	}

239 240 241
	ret = dvb_net_init(&adap->dvb_adap, &adap->dvb_net, &adap->demux.dmx);
	if (ret < 0) {
		err("dvb_net_init failed: error %d", ret);
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322
		goto err_net_init;
	}

	adap->state |= DVB_USB_ADAP_STATE_DVB;
	return 0;

err_net_init:
	dvb_dmxdev_release(&adap->dmxdev);
err_dmx_dev:
	dvb_dmx_release(&adap->demux);
err_dmx:
	dvb_unregister_adapter(&adap->dvb_adap);
err:
	return ret;
}

int dvb_usb_adapter_dvb_exit(struct dvb_usb_adapter *adap)
{
	if (adap->state & DVB_USB_ADAP_STATE_DVB) {
		deb_info("unregistering DVB part\n");
		dvb_net_release(&adap->dvb_net);
		adap->demux.dmx.close(&adap->demux.dmx);
		dvb_dmxdev_release(&adap->dmxdev);
		dvb_dmx_release(&adap->demux);
		dvb_unregister_adapter(&adap->dvb_adap);
		adap->state &= ~DVB_USB_ADAP_STATE_DVB;
	}
	return 0;
}

static int dvb_usb_set_active_fe(struct dvb_frontend *fe, int onoff)
{
	struct dvb_usb_adapter *adap = fe->dvb->priv;

	int ret = (adap->props.frontend_ctrl) ?
		adap->props.frontend_ctrl(fe, onoff) : 0;

	if (ret < 0) {
		err("frontend_ctrl request failed");
		return ret;
	}
	if (onoff)
		adap->active_fe = fe->id;

	return 0;
}

static int dvb_usb_fe_wakeup(struct dvb_frontend *fe)
{
	struct dvb_usb_adapter *adap = fe->dvb->priv;

	dvb_usb_device_power_ctrl(adap->dev, 1);

	dvb_usb_set_active_fe(fe, 1);

	if (adap->fe_adap[fe->id].fe_init)
		adap->fe_adap[fe->id].fe_init(fe);

	return 0;
}

static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
{
	struct dvb_usb_adapter *adap = fe->dvb->priv;

	if (adap->fe_adap[fe->id].fe_sleep)
		adap->fe_adap[fe->id].fe_sleep(fe);

	dvb_usb_set_active_fe(fe, 0);

	return dvb_usb_device_power_ctrl(adap->dev, 0);
}

int dvb_usb_adapter_frontend_init(struct dvb_usb_adapter *adap)
{
	int ret, i;

	/* register all given adapter frontends */
	for (i = 0; i < adap->props.num_frontends; i++) {

		if (adap->props.fe[i].frontend_attach == NULL) {
323
			err("strange: '%s' #%d,%d " \
324
			    "doesn't want to attach a frontend.",
325
			    adap->dev->name, adap->id, i);
326 327 328 329 330 331 332 333 334

			return 0;
		}

		ret = adap->props.fe[i].frontend_attach(adap);
		if (ret || adap->fe_adap[i].fe == NULL) {
			/* only print error when there is no FE at all */
			if (i == 0)
				err("no frontend was attached by '%s'",
335
					adap->dev->name);
336 337 338 339 340 341 342 343 344 345 346 347

			return 0;
		}

		adap->fe_adap[i].fe->id = i;

		/* re-assign sleep and wakeup functions */
		adap->fe_adap[i].fe_init = adap->fe_adap[i].fe->ops.init;
		adap->fe_adap[i].fe->ops.init  = dvb_usb_fe_wakeup;
		adap->fe_adap[i].fe_sleep = adap->fe_adap[i].fe->ops.sleep;
		adap->fe_adap[i].fe->ops.sleep = dvb_usb_fe_sleep;

348 349
		if (dvb_register_frontend(&adap->dvb_adap,
				adap->fe_adap[i].fe)) {
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
			err("Frontend %d registration failed.", i);
			dvb_frontend_detach(adap->fe_adap[i].fe);
			adap->fe_adap[i].fe = NULL;
			/* In error case, do not try register more FEs,
			 * still leaving already registered FEs alive. */
			if (i == 0)
				return -ENODEV;
			else
				return 0;
		}

		/* only attach the tuner if the demod is there */
		if (adap->props.fe[i].tuner_attach != NULL)
			adap->props.fe[i].tuner_attach(adap);

		adap->num_frontends_initialized++;
	}

	return 0;
}

int dvb_usb_adapter_frontend_exit(struct dvb_usb_adapter *adap)
{
	int i = adap->num_frontends_initialized - 1;

	/* unregister all given adapter frontends */
	for (; i >= 0; i--) {
		if (adap->fe_adap[i].fe != NULL) {
			dvb_unregister_frontend(adap->fe_adap[i].fe);
			dvb_frontend_detach(adap->fe_adap[i].fe);
		}
	}
	adap->num_frontends_initialized = 0;

	return 0;
}