drivers/media/usb/dvb-usb/dvb-usb-init.c

Source file repositories/reference/linux-study-clean/drivers/media/usb/dvb-usb/dvb-usb-init.c

File Facts

System
Linux kernel
Corpus path
drivers/media/usb/dvb-usb/dvb-usb-init.c
Extension
.c
Size
9826 bytes
Lines
351
Domain
Driver Families
Bucket
drivers/media
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

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;
			}

			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;
			}

			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;
			}

			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;
				}
			}
		}

		if (adap->props.size_of_priv > 0) {
			adap->priv = kzalloc(adap->props.size_of_priv, GFP_KERNEL);
			if (adap->priv == NULL) {
				err("no memory for priv for adapter %d.", n);
				return -ENOMEM;
			}
		}

		ret = dvb_usb_adapter_stream_init(adap);
		if (ret)
			goto stream_init_err;

		ret = dvb_usb_adapter_dvb_init(adap, adapter_nrs);
		if (ret)
			goto dvb_init_err;

		ret = dvb_usb_adapter_frontend_init(adap);
		if (ret)
			goto frontend_init_err;

		/* use exclusive FE lock if there is multiple shared FEs */
		if (adap->fe_adap[1].fe && adap->dvb_adap.mfe_shared < 1)
			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 occurs, this helps
	 */
	if (d->props.generic_bulk_ctrl_endpoint != 0) {
		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));
	}

	return 0;

frontend_init_err:
	dvb_usb_adapter_dvb_exit(adap);
dvb_init_err:
	dvb_usb_adapter_stream_exit(adap);
stream_init_err:
	kfree(adap->priv);
	return ret;
}

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);

Annotation

Implementation Notes