dvb_usb_init.c 7.7 KB
Newer Older
1 2 3 4 5 6 7 8
/*
 * DVB USB library - provides a generic interface for a DVB USB device driver.
 *
 * dvb-usb-init.c
 *
 * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
 *
 *	This program is free software; you can redistribute it and/or modify it
9 10
 *	under the terms of the GNU General Public License as published by the
 *	Free Software Foundation, version 2.
11 12 13 14 15 16 17 18
 *
 * see Documentation/dvb/README.dvb-usb for more information
 */
#include "dvb_usb_common.h"

/* debug */
int dvb_usb_debug;
module_param_named(debug, dvb_usb_debug, int, 0644);
19 20 21
MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,pll=4,ts=8"\
		",err=16,rc=32,fw=64,mem=128,uxfer=256  (or-able))."
		DVB_USB_DEBUG_STATUS);
22 23 24

int dvb_usb_disable_rc_polling;
module_param_named(disable_rc_polling, dvb_usb_disable_rc_polling, int, 0644);
25 26
MODULE_PARM_DESC(disable_rc_polling,
		"disable remote control polling (default: 0).");
27 28

static int dvb_usb_force_pid_filter_usage;
29 30 31 32
module_param_named(force_pid_filter_usage, dvb_usb_force_pid_filter_usage,
		int, 0444);
MODULE_PARM_DESC(force_pid_filter_usage, "force all dvb-usb-devices to use a" \
		" PID filter, if any (default: 0).");
33

34
static int dvb_usb_adapter_init(struct dvb_usb_device *d)
35 36 37 38 39 40 41 42 43
{
	struct dvb_usb_adapter *adap;
	int ret, n, o;

	for (n = 0; n < d->props.num_adapters; n++) {
		adap = &d->adapter[n];
		adap->dev = d;
		adap->id  = n;

44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
		memcpy(&adap->props, &d->props.adapter[n],
				sizeof(struct dvb_usb_adapter_properties));

		for (o = 0; o < adap->props.num_frontends; o++) {
			struct dvb_usb_adapter_fe_properties *props =
					&adap->props.fe[o];
			/* speed - when running at FULL speed we need a HW
			 * PID filter */
			if (d->udev->speed == USB_SPEED_FULL &&
					!(props->caps & DVB_USB_ADAP_HAS_PID_FILTER)) {
				err("This USB2.0 device cannot be run on a" \
					" USB1.1 port. (it lacks a" \
					" hardware PID filter)");
				return -ENODEV;
			}
59

60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
			if ((d->udev->speed == USB_SPEED_FULL &&
					props->caps & DVB_USB_ADAP_HAS_PID_FILTER) ||
					(props->caps & DVB_USB_ADAP_NEED_PID_FILTERING)) {
				info("will use the device's hardware PID" \
					" filter (table count: %d).",
					props->pid_filter_count);
				adap->fe_adap[o].pid_filtering  = 1;
				adap->fe_adap[o].max_feed_count =
						props->pid_filter_count;
			} else {
				info("will pass the complete MPEG2 transport" \
					" stream to the software demuxer.");
				adap->fe_adap[o].pid_filtering  = 0;
				adap->fe_adap[o].max_feed_count = 255;
			}
75

76 77 78 79 80 81 82 83
			if (!adap->fe_adap[o].pid_filtering &&
					dvb_usb_force_pid_filter_usage &&
					props->caps & DVB_USB_ADAP_HAS_PID_FILTER) {
				info("pid filter enabled by module option.");
				adap->fe_adap[o].pid_filtering  = 1;
				adap->fe_adap[o].max_feed_count =
						props->pid_filter_count;
			}
84

85 86 87 88 89 90 91
			if (props->size_of_priv > 0) {
				adap->fe_adap[o].priv = kzalloc(props->size_of_priv, GFP_KERNEL);
				if (adap->fe_adap[o].priv == NULL) {
					err("no memory for priv for adapter" \
						" %d fe %d.", n, o);
					return -ENOMEM;
				}
92 93 94 95
			}
		}

		if (adap->props.size_of_priv > 0) {
96 97
			adap->priv = kzalloc(adap->props.size_of_priv,
					GFP_KERNEL);
98 99 100 101 102 103
			if (adap->priv == NULL) {
				err("no memory for priv for adapter %d.", n);
				return -ENOMEM;
			}
		}

104 105 106 107 108 109 110 111 112 113
		ret = dvb_usb_adapter_stream_init(adap);
		if (ret)
			return ret;

		ret = dvb_usb_adapter_dvb_init(adap);
		if (ret)
			return ret;

		ret = dvb_usb_adapter_frontend_init(adap);
		if (ret)
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
			return ret;

		/* use exclusive FE lock if there is multiple shared FEs */
		if (adap->fe_adap[1].fe)
			adap->dvb_adap.mfe_shared = 1;

		d->num_adapters_initialized++;
		d->state |= DVB_USB_STATE_DVB;
	}

	/*
	 * when reloading the driver w/o replugging the device
	 * sometimes a timeout occures, this helps
	 */
	if (d->props.generic_bulk_ctrl_endpoint != 0) {
129 130 131 132
		usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev,
			d->props.generic_bulk_ctrl_endpoint));
		usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev,
			d->props.generic_bulk_ctrl_endpoint));
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
	}

	return 0;
}

static int dvb_usb_adapter_exit(struct dvb_usb_device *d)
{
	int n;

	for (n = 0; n < d->num_adapters_initialized; n++) {
		dvb_usb_adapter_frontend_exit(&d->adapter[n]);
		dvb_usb_adapter_dvb_exit(&d->adapter[n]);
		dvb_usb_adapter_stream_exit(&d->adapter[n]);
		kfree(d->adapter[n].priv);
	}
	d->num_adapters_initialized = 0;
	d->state &= ~DVB_USB_STATE_DVB;
	return 0;
}


/* general initialization functions */
static int dvb_usb_exit(struct dvb_usb_device *d)
{
	deb_info("state before exiting everything: %x\n", d->state);
	dvb_usb_remote_exit(d);
	dvb_usb_adapter_exit(d);
	dvb_usb_i2c_exit(d);
	deb_info("state should be zero now: %x\n", d->state);
	d->state = DVB_USB_STATE_INIT;
	kfree(d->priv);
	kfree(d);
	return 0;
}

168
static int dvb_usb_init(struct dvb_usb_device *d)
169 170 171 172 173 174 175 176 177 178 179
{
	int ret = 0;

	mutex_init(&d->usb_mutex);
	mutex_init(&d->i2c_mutex);

	d->state = DVB_USB_STATE_INIT;

	/* check the capabilities and set appropriate variables */
	dvb_usb_device_power_ctrl(d, 1);

180 181 182 183 184
	ret = dvb_usb_i2c_init(d);
	if (ret == 0)
		ret = dvb_usb_adapter_init(d);

	if (ret) {
185 186 187 188
		dvb_usb_exit(d);
		return ret;
	}

189 190 191
	if (d->props.init)
		d->props.init(d);

192 193
	ret = dvb_usb_remote_init(d);
	if (ret)
194 195 196 197 198 199 200 201 202 203 204 205 206 207
		err("could not initialize remote control.");

	dvb_usb_device_power_ctrl(d, 0);

	return 0;
}

int dvb_usb_device_power_ctrl(struct dvb_usb_device *d, int onoff)
{
	if (onoff)
		d->powered++;
	else
		d->powered--;

208 209
	if (d->powered == 0 || (onoff && d->powered == 1)) {
		/* when switching from 1 to 0 or from 0 to 1 */
210 211 212 213 214 215 216 217 218 219 220
		deb_info("power control: %d\n", onoff);
		if (d->props.power_ctrl)
			return d->props.power_ctrl(d, onoff);
	}
	return 0;
}

/*
 * USB
 */
int dvb_usbv2_device_init(struct usb_interface *intf,
221
		const struct usb_device_id *id)
222 223 224
{
	struct usb_device *udev = interface_to_usbdev(intf);
	struct dvb_usb_device *d = NULL;
225 226 227
	struct dvb_usb_driver_info *driver_info =
			(struct dvb_usb_driver_info *) id->driver_info;
	const struct dvb_usb_device_properties *props = driver_info->props;
228
	int ret = -ENOMEM;
229
	bool cold = false;
230 231 232 233 234 235 236 237

	d = kzalloc(sizeof(struct dvb_usb_device), GFP_KERNEL);
	if (d == NULL) {
		err("no memory for 'struct dvb_usb_device'");
		return -ENOMEM;
	}

	d->udev = udev;
238
	d->name = driver_info->name;
239
	memcpy(&d->props, props, sizeof(struct dvb_usb_device_properties));
240

241 242 243 244 245 246 247 248
	if (d->props.size_of_priv > 0) {
		d->priv = kzalloc(d->props.size_of_priv, GFP_KERNEL);
		if (d->priv == NULL) {
			err("no memory for priv in 'struct dvb_usb_device'");
			ret = -ENOMEM;
			goto err_kfree;
		}
	}
249

250 251 252 253 254 255 256 257 258 259
	if (d->props.identify_state) {
		ret = d->props.identify_state(d);
		if (ret == 0) {
			;
		} else if (ret == COLD) {
			cold = true;
			ret = 0;
		} else {
			goto err_kfree;
		}
260 261 262
	}

	if (cold) {
263
		info("found a '%s' in cold state, will try to load a firmware",
264
				d->name);
265 266 267 268 269 270 271 272 273
		ret = dvb_usb_download_firmware(d);
		if (ret == 0) {
			;
		} else if (ret == RECONNECTS_USB) {
			ret = 0;
			goto err_kfree;
		} else {
			goto err_kfree;
		}
274 275
	}

276
	info("found a '%s' in warm state.", d->name);
277 278 279

	usb_set_intfdata(intf, d);

280
	ret = dvb_usb_init(d);
281 282

	if (ret == 0)
283
		info("%s successfully initialized and connected.", d->name);
284
	else
285
		info("%s error while loading driver (%d)", d->name, ret);
286 287 288 289 290 291 292

	return 0;

err_kfree:
	kfree(d->priv);
	kfree(d);

293 294 295 296 297 298 299
	return ret;
}
EXPORT_SYMBOL(dvb_usbv2_device_init);

void dvb_usbv2_device_exit(struct usb_interface *intf)
{
	struct dvb_usb_device *d = usb_get_intfdata(intf);
300
	const char *name;
301 302

	usb_set_intfdata(intf, NULL);
303 304
	if (d) {
		name = d->name;
305 306 307 308 309 310 311 312 313 314
		dvb_usb_exit(d);
	}
	info("%s successfully deinitialized and disconnected.", name);
}
EXPORT_SYMBOL(dvb_usbv2_device_exit);

MODULE_VERSION("1.0");
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
MODULE_DESCRIPTION("A library module containing commonly used USB and DVB function USB DVB devices");
MODULE_LICENSE("GPL");