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
next prev 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