summaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorHeikki Krogerus <heikki.krogerus@linux.intel.com>2020-02-11 14:25:26 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-02-12 10:51:21 -0800
commitb747038d9d14a2ca9e6f139a8584507d5aed8634 (patch)
tree1ba9f3816390a704f39e6e4df86f590ab6b112b2 /drivers/usb
parent882f7a4dae1db3f33934453d4194b829cd8ec5a5 (diff)
downloadlinux-b747038d9d14a2ca9e6f139a8584507d5aed8634.tar.bz2
usb: typec: Make the attributes read-only when writing is not possible
This affects the read-writable attribute files. Before this there was no way for the user to know is changing the value supported or not. >From now on those attribute files will be made read-only unless the underlying driver supports changing of the value. Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Link: https://lore.kernel.org/r/20200211112531.86510-2-heikki.krogerus@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/typec/class.c65
1 files changed, 63 insertions, 2 deletions
diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c
index 7c44e930602f..a451ae181fe9 100644
--- a/drivers/usb/typec/class.c
+++ b/drivers/usb/typec/class.c
@@ -432,7 +432,28 @@ static struct attribute *typec_altmode_attrs[] = {
&dev_attr_vdo.attr,
NULL
};
-ATTRIBUTE_GROUPS(typec_altmode);
+
+static umode_t typec_altmode_attr_is_visible(struct kobject *kobj,
+ struct attribute *attr, int n)
+{
+ struct typec_altmode *adev = to_typec_altmode(kobj_to_dev(kobj));
+
+ if (attr == &dev_attr_active.attr)
+ if (!adev->ops || !adev->ops->activate)
+ return 0444;
+
+ return attr->mode;
+}
+
+static struct attribute_group typec_altmode_group = {
+ .is_visible = typec_altmode_attr_is_visible,
+ .attrs = typec_altmode_attrs,
+};
+
+static const struct attribute_group *typec_altmode_groups[] = {
+ &typec_altmode_group,
+ NULL
+};
static int altmode_id_get(struct device *dev)
{
@@ -1305,7 +1326,47 @@ static struct attribute *typec_attrs[] = {
&dev_attr_port_type.attr,
NULL,
};
-ATTRIBUTE_GROUPS(typec);
+
+static umode_t typec_attr_is_visible(struct kobject *kobj,
+ struct attribute *attr, int n)
+{
+ struct typec_port *port = to_typec_port(kobj_to_dev(kobj));
+
+ if (attr == &dev_attr_data_role.attr) {
+ if (port->cap->data != TYPEC_PORT_DRD ||
+ !port->ops || !port->ops->dr_set)
+ return 0444;
+ } else if (attr == &dev_attr_power_role.attr) {
+ if (port->cap->type != TYPEC_PORT_DRP ||
+ !port->cap->pd_revision ||
+ !port->ops || !port->ops->pr_set)
+ return 0444;
+ } else if (attr == &dev_attr_vconn_source.attr) {
+ if (!port->cap->pd_revision ||
+ !port->ops || !port->ops->vconn_set)
+ return 0444;
+ } else if (attr == &dev_attr_preferred_role.attr) {
+ if (port->cap->type != TYPEC_PORT_DRP ||
+ !port->ops || !port->ops->try_role)
+ return 0444;
+ } else if (attr == &dev_attr_port_type.attr) {
+ if (port->cap->type != TYPEC_PORT_DRP ||
+ !port->ops || !port->ops->port_type_set)
+ return 0444;
+ }
+
+ return attr->mode;
+}
+
+static struct attribute_group typec_group = {
+ .is_visible = typec_attr_is_visible,
+ .attrs = typec_attrs,
+};
+
+static const struct attribute_group *typec_groups[] = {
+ &typec_group,
+ NULL
+};
static int typec_uevent(struct device *dev, struct kobj_uevent_env *env)
{