mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Guenter Roeck <linux@roeck-us.net>
To: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Cc: Greg KH <gregkh@linuxfoundation.org>,
	Mathias Nyman <mathias.nyman@linux.intel.com>,
	Felipe Balbi <felipe.balbi@linux.intel.com>,
	Oliver Neukum <oneukum@suse.com>,
	Rajaram R <rajaram.officemail@gmail.com>,
	Andy Shevchenko <andy.shevchenko@gmail.com>,
	linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org
Subject: [RFC PATCH] usb: typec: Various API updates and fixes
Date: Wed, 25 May 2016 11:35:07 -0700	[thread overview]
Message-ID: <20160525183507.GA23019@roeck-us.net> (raw)
In-Reply-To: <1463661894-22820-1-git-send-email-heikki.krogerus@linux.intel.com>

From: Guenter Roeck <groeck@chromium.org>

New API functions (calls into class code)
	typec_set_usb_role()
	typec_set_pwr_role()
	typec_set_vconn_role()
	typec_set_pwr_opmode()

Modified API functions (calls into class code):
	typec_register_port(dev, cap) ->
			typec_register_port(dev, cap, driver_data)

Modified callback functions:
	dr_swap(port) -> dr_set(port, driver_data, role);
	pr_swap(port) -> pr_set(port, driver_data, role);
	vconn_swap(port) -> vconn_set(port, driver_data, role);
	fix_role(port) -> fix_role(port, driver_data, role);
	activate_mode(...) -> activate_mode(..., driver_data, ...);

New sysfs attribute:
	current_vconn_role

Other:
- Extract role initialization to new function typec_init_roles()
- Call driver code unconditionally on role changes
- Add NULL check in typec_unregister_altmodes()
- If an alternate mode description pointer is NULL, display
  an empty string.

Signed-off-by: Guenter Roeck <groeck@chromium.org>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
This patch applies on top of '[RFC PATCHv2] usb: USB Type-C Connector Class'
from Heikki Krogerus. It provided the changes I made to get the code
operational.

 drivers/usb/type-c/typec.c | 134 ++++++++++++++++++++++++++++++++++++---------
 include/linux/usb/typec.h  |  26 ++++++---
 2 files changed, 125 insertions(+), 35 deletions(-)

diff --git a/drivers/usb/type-c/typec.c b/drivers/usb/type-c/typec.c
index 8028b7df0951..6836e972b681 100644
--- a/drivers/usb/type-c/typec.c
+++ b/drivers/usb/type-c/typec.c
@@ -27,6 +27,8 @@ struct typec_port {
 	struct typec_partner	*partner;
 	struct typec_cable	*cable;
 
+	void			*driver_data;
+
 	unsigned int		connected:1;
 
 	int			n_altmode;
@@ -324,6 +326,20 @@ static void typec_remove_cable(struct typec_port *port)
 	device_unregister(&port->cable->dev);
 }
 
+static void typec_init_roles(struct typec_port *port)
+{
+	if (port->fixed_role == TYPEC_PORT_DFP) {
+		port->usb_role = TYPEC_HOST;
+		port->pwr_role = TYPEC_PWR_SOURCE;
+		port->vconn_role = TYPEC_PWR_SOURCE;
+	} else {
+		/* Device mode as default also with DRP ports */
+		port->usb_role = TYPEC_DEVICE;
+		port->pwr_role = TYPEC_PWR_SINK;
+		port->vconn_role = TYPEC_PWR_SINK;
+	}
+}
+
 /* -------------------------------- */
 
 int typec_connect(struct typec_port *port, struct typec_connection *con)
@@ -378,16 +394,7 @@ void typec_disconnect(struct typec_port *port)
 
 	port->pwr_opmode = TYPEC_PWR_MODE_USB;
 
-	if (port->fixed_role == TYPEC_PORT_DFP) {
-		port->usb_role = TYPEC_HOST;
-		port->pwr_role = TYPEC_PWR_SOURCE;
-		port->vconn_role = TYPEC_PWR_SOURCE;
-	} else {
-		/* Device mode as default also with DRP ports */
-		port->usb_role = TYPEC_DEVICE;
-		port->pwr_role = TYPEC_PWR_SINK;
-		port->vconn_role = TYPEC_PWR_SINK;
-	}
+	typec_init_roles(port);
 
 	kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
 }
@@ -405,6 +412,34 @@ struct typec_port *typec_dev2port(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(typec_dev2port);
 
+/* --------------------------------------- */
+/* Driver callbacks to report role updates */
+
+void typec_set_usb_role(struct typec_port *port, enum typec_usb_role role)
+{
+	port->usb_role = role;
+}
+EXPORT_SYMBOL(typec_set_usb_role);
+
+void typec_set_pwr_role(struct typec_port *port, enum typec_pwr_role role)
+{
+	port->pwr_role = role;
+}
+EXPORT_SYMBOL(typec_set_pwr_role);
+
+void typec_set_vconn_role(struct typec_port *port, enum typec_pwr_role role)
+{
+	port->vconn_role = role;
+}
+EXPORT_SYMBOL(typec_set_vconn_role);
+
+void typec_set_pwr_opmode(struct typec_port *port,
+			  enum typec_pwr_opmode opmode)
+{
+	port->pwr_opmode = opmode;
+}
+EXPORT_SYMBOL(typec_set_pwr_opmode);
+
 /* -------------------------------- */
 /* Alternate Modes */
 
@@ -451,7 +486,7 @@ typec_altmode_desc_show(struct device *dev, struct device_attribute *attr,
 	struct typec_mode *mode = container_of(attr, struct typec_mode,
 					       desc_attr);
 
-	return sprintf(buf, "%s\n", mode->desc);
+	return sprintf(buf, "%s\n", mode->desc ? mode->desc : "");
 }
 
 static ssize_t
@@ -561,6 +596,9 @@ void typec_unregister_altmodes(struct typec_altmode *alt_modes)
 {
 	struct typec_altmode *alt;
 
+	if (!alt_modes)
+		return;
+
 	for (alt = alt_modes; alt->svid; alt++)
 		device_unregister(&alt->dev);
 }
@@ -581,7 +619,7 @@ current_usb_data_role_store(struct device *dev, struct device_attribute *attr,
 		return -EOPNOTSUPP;
 	}
 
-	if (!port->cap->dr_swap) {
+	if (!port->cap->dr_set) {
 		dev_warn(dev, "data role swapping not supported\n");
 		return -EOPNOTSUPP;
 	}
@@ -593,10 +631,7 @@ current_usb_data_role_store(struct device *dev, struct device_attribute *attr,
 	else
 		return -EINVAL;
 
-	if (port->usb_role == role || !port->partner)
-		return size;
-
-	ret = port->cap->dr_swap(port);
+	ret = port->cap->dr_set(port, port->driver_data, role);
 	if (ret)
 		return ret;
 
@@ -655,10 +690,7 @@ current_data_role_store(struct device *dev, struct device_attribute *attr,
 	else
 		return -EINVAL;
 
-	if (port->fixed_role == role)
-		return size;
-
-	ret = port->cap->fix_role(port, role);
+	ret = port->cap->fix_role(port, port->driver_data, role);
 	if (ret)
 		return ret;
 
@@ -688,7 +720,7 @@ static ssize_t current_power_role_store(struct device *dev,
 		return -EOPNOTSUPP;
 	}
 
-	if (!port->cap->pr_swap) {
+	if (!port->cap->pr_set) {
 		dev_warn(dev, "power role swapping not supported\n");
 		return -EOPNOTSUPP;
 	}
@@ -705,10 +737,7 @@ static ssize_t current_power_role_store(struct device *dev,
 	else
 		return -EINVAL;
 
-	if (port->pwr_role == role || !port->partner)
-		return size;
-
-	ret = port->cap->pr_swap(port);
+	ret = port->cap->pr_set(port, port->driver_data, role);
 	if (ret)
 		return ret;
 
@@ -762,6 +791,54 @@ static ssize_t power_operation_mode_show(struct device *dev,
 }
 static DEVICE_ATTR_RO(power_operation_mode);
 
+static ssize_t current_vconn_role_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t size)
+{
+	struct typec_port *port = to_typec_port(dev);
+	enum typec_pwr_role role;
+	int ret;
+
+	if (!port->cap->usb_pd) {
+		dev_dbg(dev, "vconn swap only supported with USB PD\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (!port->cap->vconn_set) {
+		dev_warn(dev, "vconn swapping not supported\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (!strncmp(buf, "source", 6))
+		role = TYPEC_PWR_SOURCE;
+	else if (!strncmp(buf, "sink", 4))
+		role = TYPEC_PWR_SINK;
+	else
+		return -EINVAL;
+
+	ret = port->cap->vconn_set(port, port->driver_data, role);
+	if (ret)
+		return ret;
+
+	return size;
+}
+
+static ssize_t current_vconn_role_show(struct device *dev,
+				       struct device_attribute *attr, char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	switch (port->vconn_role) {
+	case TYPEC_PWR_SOURCE:
+		return sprintf(buf, "source\n");
+	case TYPEC_PWR_SINK:
+		return sprintf(buf, "sink\n");
+	default:
+		return sprintf(buf, "unknown\n");
+	};
+}
+static DEVICE_ATTR_RW(current_vconn_role);
+
 static ssize_t supports_audio_accessory_show(struct device *dev,
 					     struct device_attribute *attr,
 					     char *buf)
@@ -795,6 +872,7 @@ static DEVICE_ATTR_RO(supports_usb_power_delivery);
 static struct attribute *typec_attrs[] = {
 	&dev_attr_current_data_role.attr,
 	&dev_attr_current_power_role.attr,
+	&dev_attr_current_vconn_role.attr,
 	&dev_attr_current_usb_data_role.attr,
 	&dev_attr_power_operation_mode.attr,
 	&dev_attr_supported_data_roles.attr,
@@ -862,7 +940,8 @@ static struct device_type typec_port_dev_type = {
 };
 
 struct typec_port *typec_register_port(struct device *dev,
-				       struct typec_capability *cap)
+				       struct typec_capability *cap,
+				       void *driver_data)
 {
 	struct typec_port *port;
 	int ret;
@@ -880,6 +959,7 @@ struct typec_port *typec_register_port(struct device *dev,
 
 	port->id = id;
 	port->cap = cap;
+	port->driver_data = driver_data;
 	port->dev.type = &typec_port_dev_type;
 	port->dev.class = &typec_class;
 	port->dev.parent = dev;
@@ -888,6 +968,8 @@ struct typec_port *typec_register_port(struct device *dev,
 
 	port->fixed_role = port->cap->role;
 
+	typec_init_roles(port);
+
 	ret = device_register(&port->dev);
 	if (ret) {
 		ida_simple_remove(&typec_index_ida, id);
diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h
index 86e5c867800b..d16a38de57ac 100644
--- a/include/linux/usb/typec.h
+++ b/include/linux/usb/typec.h
@@ -168,9 +168,9 @@ struct typec_partner {
  * @audio_accessory: Audio Accessory Adapter Mode support
  * @debug_accessory: Debug Accessory Mode support
  * @fix_role: Set a fixed data role for DRP port
- * @dr_swap: Data Role Swap support
- * @pr_swap: Power Role Swap support
- * @vconn_swap: VCONN Swap support
+ * @dr_set: Set Data Role
+ * @pr_set: Set Power Role
+ * @vconn_set: Set VCONN Role
  * @activate_mode: Enter/exit given Alternate Mode
  *
  * Static capabilities of a single USB Type-C port.
@@ -182,14 +182,14 @@ struct typec_capability {
 	unsigned int		audio_accessory:1;
 	unsigned int		debug_accessory:1;
 
-	int			(*fix_role)(struct typec_port *,
+	int			(*fix_role)(struct typec_port *, void *,
 					    enum typec_data_role);
 
-	int			(*dr_swap)(struct typec_port *);
-	int			(*pr_swap)(struct typec_port *);
-	int			(*vconn_swap)(struct typec_port *);
+	int			(*dr_set)(struct typec_port *, void *, enum typec_usb_role);
+	int			(*pr_set)(struct typec_port *, void *, enum typec_pwr_role);
+	int			(*vconn_set)(struct typec_port *, void *, enum typec_pwr_role);
 
-	int			(*activate_mode)(struct typec_altmode *,
+	int			(*activate_mode)(struct typec_altmode *, void *,
 						 int mode, int activate);
 };
 
@@ -217,7 +217,8 @@ struct typec_connection {
 };
 
 struct typec_port *typec_register_port(struct device *dev,
-				       struct typec_capability *cap);
+				       struct typec_capability *cap,
+				       void *driver_data);
 void typec_unregister_port(struct typec_port *port);
 
 int typec_connect(struct typec_port *port, struct typec_connection *con);
@@ -227,4 +228,11 @@ void typec_disconnect(struct typec_port *port);
 struct device *typec_port2dev(struct typec_port *port);
 struct typec_port *typec_dev2port(struct device *dev);
 
+/* Callbacks from driver */
+
+void typec_set_usb_role(struct typec_port *, enum typec_usb_role);
+void typec_set_pwr_role(struct typec_port *, enum typec_pwr_role);
+void typec_set_vconn_role(struct typec_port *, enum typec_pwr_role);
+void typec_set_pwr_opmode(struct typec_port *, enum typec_pwr_opmode);
+
 #endif /* __LINUX_USB_TYPEC_H */
-- 
2.5.0

  parent reply	other threads:[~2016-05-25 18:35 UTC|newest]

Thread overview: 98+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-05-19 12:44 [RFC PATCHv2] usb: USB Type-C Connector Class Heikki Krogerus
2016-05-19 14:47 ` Oliver Neukum
2016-05-20 11:24   ` Heikki Krogerus
2016-05-20 13:37     ` Oliver Neukum
2016-05-21  5:51       ` Guenter Roeck
2016-05-21  6:43         ` Oliver Neukum
2016-05-22 15:54           ` Guenter Roeck
2016-05-23  5:34             ` Oliver Neukum
2016-05-23 13:27               ` Guenter Roeck
2016-05-23 13:58                 ` Oliver Neukum
2016-05-23 14:43                   ` Guenter Roeck
2016-05-23 15:55                     ` Oliver Neukum
2016-05-23 16:52                       ` Guenter Roeck
2016-05-24 10:08                         ` Heikki Krogerus
2016-05-24 10:18                           ` Oliver Neukum
2016-05-24 11:04                             ` Heikki Krogerus
2016-05-19 14:48 ` Oliver Neukum
2016-05-19 15:43   ` Greg KH
2016-05-20 10:58     ` Heikki Krogerus
2016-05-19 17:53 ` Guenter Roeck
2016-05-20 10:47   ` Heikki Krogerus
2016-05-20 17:02     ` Guenter Roeck
2016-05-23  9:23       ` Heikki Krogerus
2016-05-20 14:19 ` Oliver Neukum
2016-05-23  9:57   ` Heikki Krogerus
2016-05-23 11:25     ` Oliver Neukum
2016-05-23 17:09       ` Guenter Roeck
2016-05-24  9:06         ` Oliver Neukum
2016-05-24  9:32       ` Heikki Krogerus
2016-05-24 12:51 ` Oliver Neukum
2016-05-25 11:28   ` Heikki Krogerus
2016-05-25 15:19     ` Guenter Roeck
2016-05-27  7:30       ` Heikki Krogerus
2016-05-24 13:42 ` Guenter Roeck
2016-05-25 11:30   ` Heikki Krogerus
2016-05-25 13:12     ` Guenter Roeck
2016-05-24 19:28 ` Guenter Roeck
2016-05-25 11:51   ` Heikki Krogerus
2016-05-25 13:21     ` Guenter Roeck
2016-05-25 14:04       ` Heikki Krogerus
2016-05-25 14:20         ` Oliver Neukum
2016-05-25 14:59           ` Guenter Roeck
2016-05-27  7:29             ` Heikki Krogerus
2016-05-25 18:35 ` Guenter Roeck [this message]
2016-05-27  7:55   ` [RFC PATCH] usb: typec: Various API updates and fixes Heikki Krogerus
2016-05-27 14:06     ` Guenter Roeck
2016-05-30 12:48       ` Heikki Krogerus
2016-05-30 13:19 ` [RFC PATCHv2] usb: USB Type-C Connector Class Heikki Krogerus
2016-05-30 13:59   ` Oliver Neukum
2016-05-31  8:31     ` Heikki Krogerus
2016-05-31  8:48       ` Oliver Neukum
2016-05-31 12:09         ` Heikki Krogerus
2016-05-31 12:43           ` Heikki Krogerus
2016-05-31 17:20             ` Guenter Roeck
2016-06-01  8:23               ` Heikki Krogerus
2016-06-01  8:31                 ` Oliver Neukum
2016-06-01  9:04                 ` Oliver Neukum
2016-06-01 13:34                   ` Guenter Roeck
2016-06-02  6:24                     ` Oliver Neukum
2016-06-02  6:37                       ` Guenter Roeck
2016-06-02  7:43                         ` Oliver Neukum
2016-05-31 17:14       ` Guenter Roeck
2016-06-01  9:26 ` Oliver Neukum
2016-06-01 23:29   ` Guenter Roeck
2016-06-02  6:30     ` Oliver Neukum
2016-06-02  8:27       ` Heikki Krogerus
2016-06-02 10:18     ` Heikki Krogerus
2016-06-02 16:12       ` Guenter Roeck
2016-06-03 13:21         ` Heikki Krogerus
2016-06-03 13:51           ` Guenter Roeck
2016-06-03 15:17             ` Heikki Krogerus
2016-06-03 18:39               ` Guenter Roeck
2016-06-06 13:28                 ` Heikki Krogerus
2016-06-06 13:35                   ` Oliver Neukum
2016-06-07  8:23                     ` Heikki Krogerus
2016-06-07 16:57                   ` Guenter Roeck
2016-06-02  8:02   ` Heikki Krogerus
2016-06-03 20:20 ` Pavel Machek
2016-06-06 13:45   ` Heikki Krogerus
2016-06-06 14:41     ` Greg KH
2016-06-07  8:25       ` Heikki Krogerus
2016-06-06 16:02     ` Guenter Roeck
2016-06-10 14:34 ` [RFC PATCHv3] " Heikki Krogerus
2016-06-11  7:05   ` Oliver Neukum
2016-06-11 18:03     ` Guenter Roeck
2016-06-13  7:49       ` Heikki Krogerus
2016-06-13  7:48     ` Heikki Krogerus
2016-06-21 13:08 ` [RFC PATCHv2] " Oliver Neukum
2016-06-21 13:24   ` Guenter Roeck
2016-06-21 19:43     ` Oliver Neukum
2016-06-21 21:37       ` Guenter Roeck
2016-06-21 13:58   ` Heikki Krogerus
2016-06-21 20:43     ` Oliver Neukum
2016-06-22  9:31       ` Heikki Krogerus
2016-06-22 10:08         ` Oliver Neukum
2016-06-22 11:19           ` Heikki Krogerus
2016-08-07 21:37           ` Pavel Machek
2016-08-08  8:52             ` Oliver Neukum

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160525183507.GA23019@roeck-us.net \
    --to=linux@roeck-us.net \
    --cc=andy.shevchenko@gmail.com \
    --cc=felipe.balbi@linux.intel.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=heikki.krogerus@linux.intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=mathias.nyman@linux.intel.com \
    --cc=oneukum@suse.com \
    --cc=rajaram.officemail@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome