linux USB --- 监听 USB 角色

 

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

 

posted @ 2025-11-13 20:51  流水灯  阅读(17)  评论(0)    收藏  举报