linux/drivers/usb/roles/class.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * USB Role Switch Support
   4 *
   5 * Copyright (C) 2018 Intel Corporation
   6 * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
   7 *         Hans de Goede <hdegoede@redhat.com>
   8 */
   9
  10#include <linux/usb/role.h>
  11#include <linux/property.h>
  12#include <linux/device.h>
  13#include <linux/module.h>
  14#include <linux/mutex.h>
  15#include <linux/slab.h>
  16
  17static struct class *role_class;
  18
  19struct usb_role_switch {
  20        struct device dev;
  21        struct mutex lock; /* device lock*/
  22        enum usb_role role;
  23
  24        /* From descriptor */
  25        struct device *usb2_port;
  26        struct device *usb3_port;
  27        struct device *udc;
  28        usb_role_switch_set_t set;
  29        usb_role_switch_get_t get;
  30        bool allow_userspace_control;
  31};
  32
  33#define to_role_switch(d)       container_of(d, struct usb_role_switch, dev)
  34
  35/**
  36 * usb_role_switch_set_role - Set USB role for a switch
  37 * @sw: USB role switch
  38 * @role: USB role to be switched to
  39 *
  40 * Set USB role @role for @sw.
  41 */
  42int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role)
  43{
  44        int ret;
  45
  46        if (IS_ERR_OR_NULL(sw))
  47                return 0;
  48
  49        mutex_lock(&sw->lock);
  50
  51        ret = sw->set(sw, role);
  52        if (!ret) {
  53                sw->role = role;
  54                kobject_uevent(&sw->dev.kobj, KOBJ_CHANGE);
  55        }
  56
  57        mutex_unlock(&sw->lock);
  58
  59        return ret;
  60}
  61EXPORT_SYMBOL_GPL(usb_role_switch_set_role);
  62
  63/**
  64 * usb_role_switch_get_role - Get the USB role for a switch
  65 * @sw: USB role switch
  66 *
  67 * Depending on the role-switch-driver this function returns either a cached
  68 * value of the last set role, or reads back the actual value from the hardware.
  69 */
  70enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw)
  71{
  72        enum usb_role role;
  73
  74        if (IS_ERR_OR_NULL(sw))
  75                return USB_ROLE_NONE;
  76
  77        mutex_lock(&sw->lock);
  78
  79        if (sw->get)
  80                role = sw->get(sw);
  81        else
  82                role = sw->role;
  83
  84        mutex_unlock(&sw->lock);
  85
  86        return role;
  87}
  88EXPORT_SYMBOL_GPL(usb_role_switch_get_role);
  89
  90static void *usb_role_switch_match(struct fwnode_handle *fwnode, const char *id,
  91                                   void *data)
  92{
  93        struct device *dev;
  94
  95        if (id && !fwnode_property_present(fwnode, id))
  96                return NULL;
  97
  98        dev = class_find_device_by_fwnode(role_class, fwnode);
  99
 100        return dev ? to_role_switch(dev) : ERR_PTR(-EPROBE_DEFER);
 101}
 102
 103static struct usb_role_switch *
 104usb_role_switch_is_parent(struct fwnode_handle *fwnode)
 105{
 106        struct fwnode_handle *parent = fwnode_get_parent(fwnode);
 107        struct device *dev;
 108
 109        if (!parent || !fwnode_property_present(parent, "usb-role-switch"))
 110                return NULL;
 111
 112        dev = class_find_device_by_fwnode(role_class, parent);
 113        return dev ? to_role_switch(dev) : ERR_PTR(-EPROBE_DEFER);
 114}
 115
 116/**
 117 * usb_role_switch_get - Find USB role switch linked with the caller
 118 * @dev: The caller device
 119 *
 120 * Finds and returns role switch linked with @dev. The reference count for the
 121 * found switch is incremented.
 122 */
 123struct usb_role_switch *usb_role_switch_get(struct device *dev)
 124{
 125        struct usb_role_switch *sw;
 126
 127        sw = usb_role_switch_is_parent(dev_fwnode(dev));
 128        if (!sw)
 129                sw = device_connection_find_match(dev, "usb-role-switch", NULL,
 130                                                  usb_role_switch_match);
 131
 132        if (!IS_ERR_OR_NULL(sw))
 133                WARN_ON(!try_module_get(sw->dev.parent->driver->owner));
 134
 135        return sw;
 136}
 137EXPORT_SYMBOL_GPL(usb_role_switch_get);
 138
 139/**
 140 * fwnode_usb_role_switch_get - Find USB role switch linked with the caller
 141 * @fwnode: The caller device node
 142 *
 143 * This is similar to the usb_role_switch_get() function above, but it searches
 144 * the switch using fwnode instead of device entry.
 145 */
 146struct usb_role_switch *fwnode_usb_role_switch_get(struct fwnode_handle *fwnode)
 147{
 148        struct usb_role_switch *sw;
 149
 150        sw = usb_role_switch_is_parent(fwnode);
 151        if (!sw)
 152                sw = fwnode_connection_find_match(fwnode, "usb-role-switch",
 153                                                  NULL, usb_role_switch_match);
 154        if (!IS_ERR_OR_NULL(sw))
 155                WARN_ON(!try_module_get(sw->dev.parent->driver->owner));
 156
 157        return sw;
 158}
 159EXPORT_SYMBOL_GPL(fwnode_usb_role_switch_get);
 160
 161/**
 162 * usb_role_switch_put - Release handle to a switch
 163 * @sw: USB Role Switch
 164 *
 165 * Decrement reference count for @sw.
 166 */
 167void usb_role_switch_put(struct usb_role_switch *sw)
 168{
 169        if (!IS_ERR_OR_NULL(sw)) {
 170                module_put(sw->dev.parent->driver->owner);
 171                put_device(&sw->dev);
 172        }
 173}
 174EXPORT_SYMBOL_GPL(usb_role_switch_put);
 175
 176/**
 177 * usb_role_switch_find_by_fwnode - Find USB role switch with its fwnode
 178 * @fwnode: fwnode of the USB Role Switch
 179 *
 180 * Finds and returns role switch with @fwnode. The reference count for the
 181 * found switch is incremented.
 182 */
 183struct usb_role_switch *
 184usb_role_switch_find_by_fwnode(const struct fwnode_handle *fwnode)
 185{
 186        struct device *dev;
 187
 188        if (!fwnode)
 189                return NULL;
 190
 191        dev = class_find_device_by_fwnode(role_class, fwnode);
 192        if (dev)
 193                WARN_ON(!try_module_get(dev->parent->driver->owner));
 194
 195        return dev ? to_role_switch(dev) : NULL;
 196}
 197EXPORT_SYMBOL_GPL(usb_role_switch_find_by_fwnode);
 198
 199static umode_t
 200usb_role_switch_is_visible(struct kobject *kobj, struct attribute *attr, int n)
 201{
 202        struct device *dev = kobj_to_dev(kobj);
 203        struct usb_role_switch *sw = to_role_switch(dev);
 204
 205        if (sw->allow_userspace_control)
 206                return attr->mode;
 207
 208        return 0;
 209}
 210
 211static const char * const usb_roles[] = {
 212        [USB_ROLE_NONE]         = "none",
 213        [USB_ROLE_HOST]         = "host",
 214        [USB_ROLE_DEVICE]       = "device",
 215};
 216
 217const char *usb_role_string(enum usb_role role)
 218{
 219        if (role < 0 || role >= ARRAY_SIZE(usb_roles))
 220                return "unknown";
 221
 222        return usb_roles[role];
 223}
 224EXPORT_SYMBOL_GPL(usb_role_string);
 225
 226static ssize_t
 227role_show(struct device *dev, struct device_attribute *attr, char *buf)
 228{
 229        struct usb_role_switch *sw = to_role_switch(dev);
 230        enum usb_role role = usb_role_switch_get_role(sw);
 231
 232        return sprintf(buf, "%s\n", usb_roles[role]);
 233}
 234
 235static ssize_t role_store(struct device *dev, struct device_attribute *attr,
 236                          const char *buf, size_t size)
 237{
 238        struct usb_role_switch *sw = to_role_switch(dev);
 239        int ret;
 240
 241        ret = sysfs_match_string(usb_roles, buf);
 242        if (ret < 0) {
 243                bool res;
 244
 245                /* Extra check if the user wants to disable the switch */
 246                ret = kstrtobool(buf, &res);
 247                if (ret || res)
 248                        return -EINVAL;
 249        }
 250
 251        ret = usb_role_switch_set_role(sw, ret);
 252        if (ret)
 253                return ret;
 254
 255        return size;
 256}
 257static DEVICE_ATTR_RW(role);
 258
 259static struct attribute *usb_role_switch_attrs[] = {
 260        &dev_attr_role.attr,
 261        NULL,
 262};
 263
 264static const struct attribute_group usb_role_switch_group = {
 265        .is_visible = usb_role_switch_is_visible,
 266        .attrs = usb_role_switch_attrs,
 267};
 268
 269static const struct attribute_group *usb_role_switch_groups[] = {
 270        &usb_role_switch_group,
 271        NULL,
 272};
 273
 274static int
 275usb_role_switch_uevent(struct device *dev, struct kobj_uevent_env *env)
 276{
 277        int ret;
 278
 279        ret = add_uevent_var(env, "USB_ROLE_SWITCH=%s", dev_name(dev));
 280        if (ret)
 281                dev_err(dev, "failed to add uevent USB_ROLE_SWITCH\n");
 282
 283        return ret;
 284}
 285
 286static void usb_role_switch_release(struct device *dev)
 287{
 288        struct usb_role_switch *sw = to_role_switch(dev);
 289
 290        kfree(sw);
 291}
 292
 293static const struct device_type usb_role_dev_type = {
 294        .name = "usb_role_switch",
 295        .groups = usb_role_switch_groups,
 296        .uevent = usb_role_switch_uevent,
 297        .release = usb_role_switch_release,
 298};
 299
 300/**
 301 * usb_role_switch_register - Register USB Role Switch
 302 * @parent: Parent device for the switch
 303 * @desc: Description of the switch
 304 *
 305 * USB Role Switch is a device capable or choosing the role for USB connector.
 306 * On platforms where the USB controller is dual-role capable, the controller
 307 * driver will need to register the switch. On platforms where the USB host and
 308 * USB device controllers behind the connector are separate, there will be a
 309 * mux, and the driver for that mux will need to register the switch.
 310 *
 311 * Returns handle to a new role switch or ERR_PTR. The content of @desc is
 312 * copied.
 313 */
 314struct usb_role_switch *
 315usb_role_switch_register(struct device *parent,
 316                         const struct usb_role_switch_desc *desc)
 317{
 318        struct usb_role_switch *sw;
 319        int ret;
 320
 321        if (!desc || !desc->set)
 322                return ERR_PTR(-EINVAL);
 323
 324        sw = kzalloc(sizeof(*sw), GFP_KERNEL);
 325        if (!sw)
 326                return ERR_PTR(-ENOMEM);
 327
 328        mutex_init(&sw->lock);
 329
 330        sw->allow_userspace_control = desc->allow_userspace_control;
 331        sw->usb2_port = desc->usb2_port;
 332        sw->usb3_port = desc->usb3_port;
 333        sw->udc = desc->udc;
 334        sw->set = desc->set;
 335        sw->get = desc->get;
 336
 337        sw->dev.parent = parent;
 338        sw->dev.fwnode = desc->fwnode;
 339        sw->dev.class = role_class;
 340        sw->dev.type = &usb_role_dev_type;
 341        dev_set_drvdata(&sw->dev, desc->driver_data);
 342        dev_set_name(&sw->dev, "%s-role-switch",
 343                     desc->name ? desc->name : dev_name(parent));
 344
 345        ret = device_register(&sw->dev);
 346        if (ret) {
 347                put_device(&sw->dev);
 348                return ERR_PTR(ret);
 349        }
 350
 351        /* TODO: Symlinks for the host port and the device controller. */
 352
 353        return sw;
 354}
 355EXPORT_SYMBOL_GPL(usb_role_switch_register);
 356
 357/**
 358 * usb_role_switch_unregister - Unregsiter USB Role Switch
 359 * @sw: USB Role Switch
 360 *
 361 * Unregister switch that was registered with usb_role_switch_register().
 362 */
 363void usb_role_switch_unregister(struct usb_role_switch *sw)
 364{
 365        if (!IS_ERR_OR_NULL(sw))
 366                device_unregister(&sw->dev);
 367}
 368EXPORT_SYMBOL_GPL(usb_role_switch_unregister);
 369
 370/**
 371 * usb_role_switch_set_drvdata - Assign private data pointer to a switch
 372 * @sw: USB Role Switch
 373 * @data: Private data pointer
 374 */
 375void usb_role_switch_set_drvdata(struct usb_role_switch *sw, void *data)
 376{
 377        dev_set_drvdata(&sw->dev, data);
 378}
 379EXPORT_SYMBOL_GPL(usb_role_switch_set_drvdata);
 380
 381/**
 382 * usb_role_switch_get_drvdata - Get the private data pointer of a switch
 383 * @sw: USB Role Switch
 384 */
 385void *usb_role_switch_get_drvdata(struct usb_role_switch *sw)
 386{
 387        return dev_get_drvdata(&sw->dev);
 388}
 389EXPORT_SYMBOL_GPL(usb_role_switch_get_drvdata);
 390
 391static int __init usb_roles_init(void)
 392{
 393        role_class = class_create(THIS_MODULE, "usb_role");
 394        return PTR_ERR_OR_ZERO(role_class);
 395}
 396subsys_initcall(usb_roles_init);
 397
 398static void __exit usb_roles_exit(void)
 399{
 400        class_destroy(role_class);
 401}
 402module_exit(usb_roles_exit);
 403
 404MODULE_AUTHOR("Heikki Krogerus <heikki.krogerus@linux.intel.com>");
 405MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
 406MODULE_LICENSE("GPL v2");
 407MODULE_DESCRIPTION("USB Role Class");
 408