drivers/usb/typec/bus.c

Source file repositories/reference/linux-study-clean/drivers/usb/typec/bus.c

File Facts

System
Linux kernel
Corpus path
drivers/usb/typec/bus.c
Extension
.c
Size
14401 bytes
Lines
573
Domain
Driver Families
Bucket
drivers/usb
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static int typec_match(struct device *dev, const struct device_driver *driver)
{
	const struct typec_altmode_driver *drv = to_altmode_driver(driver);
	struct typec_altmode *altmode = to_typec_altmode(dev);
	const struct typec_device_id *id;

	if (!is_typec_partner_altmode(dev))
		return 0;

	for (id = drv->id_table; id->svid; id++)
		if (id->svid == altmode->svid)
			return 1;
	return 0;
}

static int typec_uevent(const struct device *dev, struct kobj_uevent_env *env)
{
	const struct typec_altmode *altmode = to_typec_altmode(dev);

	if (!is_typec_partner_altmode(dev))
		return 0;

	if (add_uevent_var(env, "SVID=%04X", altmode->svid))
		return -ENOMEM;

	if (add_uevent_var(env, "MODE=%u", altmode->mode))
		return -ENOMEM;

	return add_uevent_var(env, "MODALIAS=typec:id%04X", altmode->svid);
}

static int typec_altmode_create_links(struct altmode *alt)
{
	struct device *port_dev = &alt->partner->adev.dev;
	struct device *dev = &alt->adev.dev;
	int err;

	err = sysfs_create_link(&dev->kobj, &port_dev->kobj, "port");
	if (err)
		return err;

	err = sysfs_create_link(&port_dev->kobj, &dev->kobj, "partner");
	if (err)
		sysfs_remove_link(&dev->kobj, "port");

	return err;
}

static void typec_altmode_remove_links(struct altmode *alt)
{
	sysfs_remove_link(&alt->partner->adev.dev.kobj, "partner");
	sysfs_remove_link(&alt->adev.dev.kobj, "port");
}

static int typec_probe(struct device *dev)
{
	struct typec_altmode_driver *drv = to_altmode_driver(dev->driver);
	struct typec_altmode *adev = to_typec_altmode(dev);
	struct altmode *altmode = to_altmode(adev);
	int ret;

	/* Fail if the port does not support the alternate mode */
	if (!altmode->partner)
		return -ENODEV;

	ret = typec_altmode_create_links(altmode);
	if (ret) {
		dev_warn(dev, "failed to create symlinks\n");
		return ret;
	}

	ret = drv->probe(adev);
	if (ret)
		typec_altmode_remove_links(altmode);

	return ret;
}

static void typec_remove(struct device *dev)
{
	struct typec_altmode_driver *drv = to_altmode_driver(dev->driver);
	struct typec_altmode *adev = to_typec_altmode(dev);
	struct altmode *altmode = to_altmode(adev);

	typec_altmode_remove_links(altmode);

	if (drv->remove)
		drv->remove(to_typec_altmode(dev));

	if (adev->active) {

Annotation

Implementation Notes