drivers/media/rc/rc-main.c

Source file repositories/reference/linux-study-clean/drivers/media/rc/rc-main.c

File Facts

System
Linux kernel
Corpus path
drivers/media/rc/rc-main.c
Extension
.c
Size
54657 bytes
Lines
2093
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

rc = device_add(&dev->dev);
	if (rc)
		goto out_rx_free;

	path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
	dev_info(&dev->dev, "%s as %s\n",
		 dev->device_name ?: "Unspecified device", path ?: "N/A");
	kfree(path);

	/*
	 * once the input device is registered in rc_setup_rx_device,
	 * userspace can open the input device and rc_open() will be called
	 * as a result. This results in driver code being allowed to submit
	 * keycodes with rc_keydown, so lirc must be registered first.
	 */
	if (dev->allowed_protocols != RC_PROTO_BIT_CEC) {
		rc = lirc_register(dev);
		if (rc < 0)
			goto out_dev;
	}

	if (dev->driver_type != RC_DRIVER_IR_RAW_TX) {
		rc = rc_setup_rx_device(dev);
		if (rc)
			goto out_lirc;
	}

	if (dev->driver_type == RC_DRIVER_IR_RAW) {
		rc = ir_raw_event_register(dev);
		if (rc < 0)
			goto out_rx;
	}

	dev_dbg(&dev->dev, "Registered rc%u (driver: %s)\n", dev->minor,
		dev->driver_name ? dev->driver_name : "unknown");

	return 0;

out_rx:
	rc_free_rx_device(dev);
out_lirc:
	if (dev->allowed_protocols != RC_PROTO_BIT_CEC)
		lirc_unregister(dev);
out_dev:
	device_del(&dev->dev);
out_rx_free:
	ir_free_table(&dev->rc_map);
out_raw:
	ir_raw_event_free(dev);
out_minor:
	ida_free(&rc_ida, minor);
	return rc;
}
EXPORT_SYMBOL_GPL(rc_register_device);

static void devm_rc_release(struct device *dev, void *res)
{
	rc_unregister_device(*(struct rc_dev **)res);
}

int devm_rc_register_device(struct device *parent, struct rc_dev *dev)
{
	struct rc_dev **dr;
	int ret;

	dr = devres_alloc(devm_rc_release, sizeof(*dr), GFP_KERNEL);
	if (!dr)
		return -ENOMEM;

	ret = rc_register_device(dev);
	if (ret) {
		devres_free(dr);
		return ret;
	}

	*dr = dev;
	devres_add(parent, dr);

	return 0;
}
EXPORT_SYMBOL_GPL(devm_rc_register_device);

void rc_unregister_device(struct rc_dev *dev)
{
	if (!dev)
		return;

	if (dev->driver_type == RC_DRIVER_IR_RAW)
		ir_raw_event_unregister(dev);

Annotation

Implementation Notes