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/device.h> 12 #include <linux/module.h> 13 #include <linux/mutex.h> 14 #include <linux/slab.h> 15 16 static struct class *role_class; 17 18 struct usb_role_switch { 19 struct device dev; 20 struct mutex lock; /* device lock*/ 21 enum usb_role role; 22 23 /* From descriptor */ 24 struct device *usb2_port; 25 struct device *usb3_port; 26 struct device *udc; 27 usb_role_switch_set_t set; 28 usb_role_switch_get_t get; 29 bool allow_userspace_control; 30 }; 31 32 #define to_role_switch(d) container_of(d, struct usb_role_switch, dev) 33 34 /** 35 * usb_role_switch_set_role - Set USB role for a switch 36 * @sw: USB role switch 37 * @role: USB role to be switched to 38 * 39 * Set USB role @role for @sw. 40 */ 41 int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role) 42 { 43 int ret; 44 45 if (IS_ERR_OR_NULL(sw)) 46 return 0; 47 48 mutex_lock(&sw->lock); 49 50 ret = sw->set(sw->dev.parent, role); 51 if (!ret) 52 sw->role = role; 53 54 mutex_unlock(&sw->lock); 55 56 return ret; 57 } 58 EXPORT_SYMBOL_GPL(usb_role_switch_set_role); 59 60 /** 61 * usb_role_switch_get_role - Get the USB role for a switch 62 * @sw: USB role switch 63 * 64 * Depending on the role-switch-driver this function returns either a cached 65 * value of the last set role, or reads back the actual value from the hardware. 66 */ 67 enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw) 68 { 69 enum usb_role role; 70 71 if (IS_ERR_OR_NULL(sw)) 72 return USB_ROLE_NONE; 73 74 mutex_lock(&sw->lock); 75 76 if (sw->get) 77 role = sw->get(sw->dev.parent); 78 else 79 role = sw->role; 80 81 mutex_unlock(&sw->lock); 82 83 return role; 84 } 85 EXPORT_SYMBOL_GPL(usb_role_switch_get_role); 86 87 static int __switch_match(struct device *dev, const void *name) 88 { 89 return !strcmp((const char *)name, dev_name(dev)); 90 } 91 92 static void *usb_role_switch_match(struct device_connection *con, int ep, 93 void *data) 94 { 95 struct device *dev; 96 97 dev = class_find_device(role_class, NULL, con->endpoint[ep], 98 __switch_match); 99 100 return dev ? to_role_switch(dev) : ERR_PTR(-EPROBE_DEFER); 101 } 102 103 /** 104 * usb_role_switch_get - Find USB role switch linked with the caller 105 * @dev: The caller device 106 * 107 * Finds and returns role switch linked with @dev. The reference count for the 108 * found switch is incremented. 109 */ 110 struct usb_role_switch *usb_role_switch_get(struct device *dev) 111 { 112 struct usb_role_switch *sw; 113 114 sw = device_connection_find_match(dev, "usb-role-switch", NULL, 115 usb_role_switch_match); 116 117 if (!IS_ERR_OR_NULL(sw)) 118 WARN_ON(!try_module_get(sw->dev.parent->driver->owner)); 119 120 return sw; 121 } 122 EXPORT_SYMBOL_GPL(usb_role_switch_get); 123 124 /** 125 * usb_role_switch_put - Release handle to a switch 126 * @sw: USB Role Switch 127 * 128 * Decrement reference count for @sw. 129 */ 130 void usb_role_switch_put(struct usb_role_switch *sw) 131 { 132 if (!IS_ERR_OR_NULL(sw)) { 133 put_device(&sw->dev); 134 module_put(sw->dev.parent->driver->owner); 135 } 136 } 137 EXPORT_SYMBOL_GPL(usb_role_switch_put); 138 139 static umode_t 140 usb_role_switch_is_visible(struct kobject *kobj, struct attribute *attr, int n) 141 { 142 struct device *dev = container_of(kobj, typeof(*dev), kobj); 143 struct usb_role_switch *sw = to_role_switch(dev); 144 145 if (sw->allow_userspace_control) 146 return attr->mode; 147 148 return 0; 149 } 150 151 static const char * const usb_roles[] = { 152 [USB_ROLE_NONE] = "none", 153 [USB_ROLE_HOST] = "host", 154 [USB_ROLE_DEVICE] = "device", 155 }; 156 157 static ssize_t 158 role_show(struct device *dev, struct device_attribute *attr, char *buf) 159 { 160 struct usb_role_switch *sw = to_role_switch(dev); 161 enum usb_role role = usb_role_switch_get_role(sw); 162 163 return sprintf(buf, "%s\n", usb_roles[role]); 164 } 165 166 static ssize_t role_store(struct device *dev, struct device_attribute *attr, 167 const char *buf, size_t size) 168 { 169 struct usb_role_switch *sw = to_role_switch(dev); 170 int ret; 171 172 ret = sysfs_match_string(usb_roles, buf); 173 if (ret < 0) { 174 bool res; 175 176 /* Extra check if the user wants to disable the switch */ 177 ret = kstrtobool(buf, &res); 178 if (ret || res) 179 return -EINVAL; 180 } 181 182 ret = usb_role_switch_set_role(sw, ret); 183 if (ret) 184 return ret; 185 186 return size; 187 } 188 static DEVICE_ATTR_RW(role); 189 190 static struct attribute *usb_role_switch_attrs[] = { 191 &dev_attr_role.attr, 192 NULL, 193 }; 194 195 static const struct attribute_group usb_role_switch_group = { 196 .is_visible = usb_role_switch_is_visible, 197 .attrs = usb_role_switch_attrs, 198 }; 199 200 static const struct attribute_group *usb_role_switch_groups[] = { 201 &usb_role_switch_group, 202 NULL, 203 }; 204 205 static int 206 usb_role_switch_uevent(struct device *dev, struct kobj_uevent_env *env) 207 { 208 int ret; 209 210 ret = add_uevent_var(env, "USB_ROLE_SWITCH=%s", dev_name(dev)); 211 if (ret) 212 dev_err(dev, "failed to add uevent USB_ROLE_SWITCH\n"); 213 214 return ret; 215 } 216 217 static void usb_role_switch_release(struct device *dev) 218 { 219 struct usb_role_switch *sw = to_role_switch(dev); 220 221 kfree(sw); 222 } 223 224 static const struct device_type usb_role_dev_type = { 225 .name = "usb_role_switch", 226 .groups = usb_role_switch_groups, 227 .uevent = usb_role_switch_uevent, 228 .release = usb_role_switch_release, 229 }; 230 231 /** 232 * usb_role_switch_register - Register USB Role Switch 233 * @parent: Parent device for the switch 234 * @desc: Description of the switch 235 * 236 * USB Role Switch is a device capable or choosing the role for USB connector. 237 * On platforms where the USB controller is dual-role capable, the controller 238 * driver will need to register the switch. On platforms where the USB host and 239 * USB device controllers behind the connector are separate, there will be a 240 * mux, and the driver for that mux will need to register the switch. 241 * 242 * Returns handle to a new role switch or ERR_PTR. The content of @desc is 243 * copied. 244 */ 245 struct usb_role_switch * 246 usb_role_switch_register(struct device *parent, 247 const struct usb_role_switch_desc *desc) 248 { 249 struct usb_role_switch *sw; 250 int ret; 251 252 if (!desc || !desc->set) 253 return ERR_PTR(-EINVAL); 254 255 sw = kzalloc(sizeof(*sw), GFP_KERNEL); 256 if (!sw) 257 return ERR_PTR(-ENOMEM); 258 259 mutex_init(&sw->lock); 260 261 sw->allow_userspace_control = desc->allow_userspace_control; 262 sw->usb2_port = desc->usb2_port; 263 sw->usb3_port = desc->usb3_port; 264 sw->udc = desc->udc; 265 sw->set = desc->set; 266 sw->get = desc->get; 267 268 sw->dev.parent = parent; 269 sw->dev.class = role_class; 270 sw->dev.type = &usb_role_dev_type; 271 dev_set_name(&sw->dev, "%s-role-switch", dev_name(parent)); 272 273 ret = device_register(&sw->dev); 274 if (ret) { 275 put_device(&sw->dev); 276 return ERR_PTR(ret); 277 } 278 279 /* TODO: Symlinks for the host port and the device controller. */ 280 281 return sw; 282 } 283 EXPORT_SYMBOL_GPL(usb_role_switch_register); 284 285 /** 286 * usb_role_switch_unregister - Unregsiter USB Role Switch 287 * @sw: USB Role Switch 288 * 289 * Unregister switch that was registered with usb_role_switch_register(). 290 */ 291 void usb_role_switch_unregister(struct usb_role_switch *sw) 292 { 293 if (!IS_ERR_OR_NULL(sw)) 294 device_unregister(&sw->dev); 295 } 296 EXPORT_SYMBOL_GPL(usb_role_switch_unregister); 297 298 static int __init usb_roles_init(void) 299 { 300 role_class = class_create(THIS_MODULE, "usb_role"); 301 return PTR_ERR_OR_ZERO(role_class); 302 } 303 subsys_initcall(usb_roles_init); 304 305 static void __exit usb_roles_exit(void) 306 { 307 class_destroy(role_class); 308 } 309 module_exit(usb_roles_exit); 310 311 MODULE_AUTHOR("Heikki Krogerus <heikki.krogerus@linux.intel.com>"); 312 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); 313 MODULE_LICENSE("GPL v2"); 314 MODULE_DESCRIPTION("USB Role Class"); 315