#include <linux/device.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/gpio/consumer.h> #include <linux/platform_device.h> #include <linux/usb/typec_dp.h> #include <linux/usb/typec_mux.h> #include <linux/usb/role.h> #include <linux/kernel.h> #include <linux/of_device.h> #include <linux/of_gpio.h>struct usb_switch {struct device *dev;struct usb_role_switch *usb_role;struct mutex lock;char role; };static int usb_switch_set_role(struct usb_role_switch *sw, enum usb_role role) {struct usb_switch *usb_switch = usb_role_switch_get_drvdata(sw);struct device *dev = usb_switch->dev;// struct platform_device *pdev = container_of(sw, struct platform_device, usb_role);// struct usb_switch *usb_switch = platform_get_drvdata(pdev); printk("%s role=%d\n", __func__, role);usb_switch->role = role;kobject_uevent(&dev->kobj, KOBJ_CHANGE);return 0; }static enum usb_role usb_switch_get_role(struct usb_role_switch *sw) {// struct platform_device *pdev = container_of(dev, struct platform_device, dev);// struct usb_switch *usb_switch = platform_get_drvdata(pdev);struct usb_switch *usb_switch = usb_role_switch_get_drvdata(sw);// struct device *dev = usb_switch->dev; printk("%s role=%d\n", __func__, usb_switch->role);return usb_switch->role; }static ssize_t role_show(struct device *dev, struct device_attribute *attr, char *buf) {struct platform_device *pdev = container_of(dev, struct platform_device, dev);struct usb_switch *usb_switch = platform_get_drvdata(pdev);return sprintf(buf, "%d", usb_switch->role); }DEVICE_ATTR(role, S_IRUGO, role_show, NULL);static int usb_switch_probe(struct platform_device *pdev) {int ret;struct usb_role_switch_desc role_desc = {};struct device *dev = &pdev->dev;struct usb_switch *usb_switch;printk("%s start\n", __func__);usb_switch = devm_kzalloc(dev, sizeof(*usb_switch), GFP_KERNEL);if (!usb_switch)return -ENOMEM;usb_switch->dev = dev;platform_set_drvdata(pdev, usb_switch);mutex_init(&usb_switch->lock);role_desc.set = usb_switch_set_role;role_desc.get = usb_switch_get_role;role_desc.allow_userspace_control = true;role_desc.fwnode = dev_fwnode(dev);role_desc.driver_data = usb_switch;usb_switch->usb_role = usb_role_switch_register(dev, &role_desc);if (IS_ERR(usb_switch->usb_role)){dev_err(dev, "failed to register typec switch\n");return ret;}device_create_file(dev, &dev_attr_role);// platform_set_drvdata(pdev, usb_switch);return 0; }static int usb_switch_remove(struct platform_device *pdev) {struct device *dev = &pdev->dev;struct usb_switch *usb_switch = platform_get_drvdata(pdev);device_remove_file(dev, &dev_attr_role);usb_role_switch_unregister(usb_switch->usb_role);return 0; }static const struct of_device_id usb_switch_match[] = {{.compatible = "usb-switch",},{} }; MODULE_DEVICE_TABLE(of, usb_switch_match);static struct platform_driver usb_switch_driver = {.probe = usb_switch_probe,.remove = usb_switch_remove,.driver = {.name = "usb_switch",.of_match_table = usb_switch_match,}, }; module_platform_driver(usb_switch_driver);MODULE_AUTHOR("XXX"); MODULE_DESCRIPTION("usb-switch driver"); MODULE_LICENSE("GPL");