dvb_usb_dvb.c 9.8 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 87
		if (adap->props.streaming_ctrl != NULL) {
			ret = adap->props.streaming_ctrl(adap, 0);
88 89 90 91 92 93 94 95 96 97 98
			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",
99
		adap->pid_filtering ?
100 101
		"yes" : "no", dvbdmxfeed->pid, dvbdmxfeed->pid,
		dvbdmxfeed->index, onoff ? "on" : "off");
102 103 104 105 106
	if (adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER &&
			adap->pid_filtering &&
			adap->props.pid_filter != NULL)
		adap->props.pid_filter(adap, dvbdmxfeed->index,
				dvbdmxfeed->pid, onoff);
107 108 109 110 111

	/* start the feed if this was the first feed and there is still a feed
	 * for reception.
	 */
	if (adap->feedcount == onoff && adap->feedcount > 0) {
112
		struct usb_data_stream_properties stream_props;
113 114 115 116 117
		unsigned int ts_props;

		/* resolve TS configuration */
		if (adap->dev->props.get_ts_config) {
			ret = adap->dev->props.get_ts_config(
118
					adap->fe[adap->active_fe],
119 120 121 122 123 124 125 126 127 128 129 130 131
					&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;
132 133 134 135

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

144
		deb_ts("submitting all URBs\n");
145
		usb_urb_submit(&adap->stream, &stream_props);
146 147

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

	}
	return 0;
}

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

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

187
int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap)
188
{
189
	int ret = dvb_register_adapter(&adap->dvb_adap, adap->dev->name,
190 191
				       adap->dev->props.owner,
				       &adap->dev->udev->dev,
192
				       adap->dev->props.adapter_nr);
193 194 195 196 197 198 199 200
	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) {
201 202 203
		if (adap->dev->props.read_mac_address(adap->dev,
				adap->dvb_adap.proposed_mac) == 0)
			info("MAC address: %pM", adap->dvb_adap.proposed_mac);
204 205 206 207 208 209 210 211 212
		else
			err("MAC address reading failed.");
	}


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

	adap->demux.filternum        = 0;
213 214
	if (adap->demux.filternum < adap->max_feed_count)
		adap->demux.filternum = adap->max_feed_count;
215 216 217 218
	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;
219 220 221
	ret = dvb_dmx_init(&adap->demux);
	if (ret < 0) {
		err("dvb_dmx_init failed: error %d", ret);
222 223 224 225 226 227
		goto err_dmx;
	}

	adap->dmxdev.filternum       = adap->demux.filternum;
	adap->dmxdev.demux           = &adap->demux.dmx;
	adap->dmxdev.capabilities    = 0;
228 229 230
	ret = dvb_dmxdev_init(&adap->dmxdev, &adap->dvb_adap);
	if (ret < 0) {
		err("dvb_dmxdev_init failed: error %d", ret);
231 232 233
		goto err_dmx_dev;
	}

234 235 236
	ret = dvb_net_init(&adap->dvb_adap, &adap->dvb_net, &adap->demux.dmx);
	if (ret < 0) {
		err("dvb_net_init failed: error %d", ret);
237 238 239 240 241 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
		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);

292 293
	if (adap->fe_init[fe->id])
		adap->fe_init[fe->id](fe);
294 295 296 297 298 299 300 301

	return 0;
}

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

302 303
	if (adap->fe_sleep[fe->id])
		adap->fe_sleep[fe->id](fe);
304 305 306 307 308 309 310 311 312 313

	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;

314
	memset(adap->fe, 0, sizeof(adap->fe));
315

316
	adap->active_fe = 0;
317

318 319 320 321 322 323
	if (adap->props.frontend_attach == NULL) {
		err("strange: '%s' doesn't want to attach a frontend.",
				adap->dev->name);
		ret = 0;
		goto err;
	}
324

325 326 327 328
	/* attach all given adapter frontends */
	ret = adap->props.frontend_attach(adap);
	if (ret < 0)
		goto err;
329

330 331 332 333 334 335 336 337
	if (adap->fe[0] == NULL) {
		err("no frontend was attached by '%s'", adap->dev->name);
		goto err;
	}

	for (i = 0; i < MAX_NO_OF_FE_PER_ADAP; i++) {
		if (adap->fe[i] == NULL)
			break;
338

339
		adap->fe[i]->id = i;
340 341

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

347 348
		ret = dvb_register_frontend(&adap->dvb_adap, adap->fe[i]);
		if (ret < 0) {
349
			err("Frontend %d registration failed.", i);
350 351
			dvb_frontend_detach(adap->fe[i]);
			adap->fe[i] = NULL;
352 353 354
			/* In error case, do not try register more FEs,
			 * still leaving already registered FEs alive. */
			if (i == 0)
355
				goto err;
356
			else
357
				break;
358 359 360 361 362
		}

		adap->num_frontends_initialized++;
	}

363 364 365 366 367 368 369
	/* attach all given adapter tuners */
	if (adap->props.tuner_attach) {
		ret = adap->props.tuner_attach(adap);
		if (ret < 0)
			err("tuner attach failed - will continue");
	}

370
	return 0;
371 372 373
err:
	pr_debug("%s: failed=%d\n", __func__, ret);
	return ret;
374 375 376 377 378 379 380 381
}

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--) {
382 383 384
		if (adap->fe[i] != NULL) {
			dvb_unregister_frontend(adap->fe[i]);
			dvb_frontend_detach(adap->fe[i]);
385 386 387 388 389 390
		}
	}
	adap->num_frontends_initialized = 0;

	return 0;
}