GNU Linux-libre 4.19.245-gnu1
[releases.git] / drivers / usb / roles / class.c
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                 module_put(sw->dev.parent->driver->owner);
134                 put_device(&sw->dev);
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");