lkml.org 
[lkml]   [2019]   [Dec]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH v2 2/3] usb: roles: Add API to register notifiers
Date
Add usb_role_switch_notifier_register() and
usb_role_switch_notifier_unregister().

The registered notifiers will be called when the USB role is changed.

Signed-off-by: Paul Cercueil <paul@crapouillou.net>
---

Notes:
v2: New patch

drivers/usb/roles/class.c | 24 +++++++++++++++++++++++-
include/linux/usb/role.h | 20 ++++++++++++++++++++
2 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c
index 8273126ffdf4..9b122b504b98 100644
--- a/drivers/usb/roles/class.c
+++ b/drivers/usb/roles/class.c
@@ -10,6 +10,7 @@
#include <linux/usb/role.h>
#include <linux/property.h>
#include <linux/device.h>
+#include <linux/notifier.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/slab.h>
@@ -19,6 +20,7 @@ static struct class *role_class;
struct usb_role_switch {
struct device dev;
struct mutex lock; /* device lock*/
+ struct blocking_notifier_head notifier_chain;
enum usb_role role;

/* From descriptor */
@@ -49,8 +51,11 @@ int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role)
mutex_lock(&sw->lock);

ret = sw->set(sw->dev.parent, role);
- if (!ret)
+ if (!ret) {
sw->role = role;
+ ret = blocking_notifier_call_chain(&sw->notifier_chain,
+ (long)role, sw);
+ }

mutex_unlock(&sw->lock);

@@ -85,6 +90,22 @@ enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw)
}
EXPORT_SYMBOL_GPL(usb_role_switch_get_role);

+int
+usb_role_switch_register_notifier(struct usb_role_switch *sw,
+ struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(&sw->notifier_chain, nb);
+}
+EXPORT_SYMBOL_GPL(usb_role_switch_register_notifier);
+
+int
+usb_role_switch_unregister_notifier(struct usb_role_switch *sw,
+ struct notifier_block *nb)
+{
+ return blocking_notifier_chain_unregister(&sw->notifier_chain, nb);
+}
+EXPORT_SYMBOL_GPL(usb_role_switch_unregister_notifier);
+
static void *usb_role_switch_match(struct device_connection *con, int ep,
void *data)
{
@@ -317,6 +338,7 @@ usb_role_switch_register(struct device *parent,
return ERR_PTR(-ENOMEM);

mutex_init(&sw->lock);
+ BLOCKING_INIT_NOTIFIER_HEAD(&sw->notifier_chain);

sw->allow_userspace_control = desc->allow_userspace_control;
sw->usb2_port = desc->usb2_port;
diff --git a/include/linux/usb/role.h b/include/linux/usb/role.h
index efac3af83d6b..5f67d42cd28d 100644
--- a/include/linux/usb/role.h
+++ b/include/linux/usb/role.h
@@ -6,6 +6,7 @@
#include <linux/device.h>

struct usb_role_switch;
+struct notifier_block;

enum usb_role {
USB_ROLE_NONE,
@@ -50,6 +51,11 @@ struct usb_role_switch *usb_role_switch_get(struct device *dev);
struct usb_role_switch *fwnode_usb_role_switch_get(struct fwnode_handle *node);
void usb_role_switch_put(struct usb_role_switch *sw);

+int usb_role_switch_register_notifier(struct usb_role_switch *sw,
+ struct notifier_block *nb);
+int usb_role_switch_unregister_notifier(struct usb_role_switch *sw,
+ struct notifier_block *nb);
+
struct usb_role_switch *
usb_role_switch_find_by_fwnode(const struct fwnode_handle *fwnode);

@@ -82,6 +88,20 @@ fwnode_usb_role_switch_get(struct fwnode_handle *node)

static inline void usb_role_switch_put(struct usb_role_switch *sw) { }

+static inline int
+usb_role_switch_register_notifier(struct usb_role_switch *sw,
+ struct notifier_block *nb)
+{
+ return ERR_PTR(-ENODEV);
+}
+
+static inline int
+usb_role_switch_unregister_notifier(struct usb_role_switch *sw,
+ struct notifier_block *nb)
+{
+ return ERR_PTR(-ENODEV);
+}
+
static inline struct usb_role_switch *
usb_role_switch_register(struct device *parent,
const struct usb_role_switch_desc *desc)
--
2.24.0
\
 
 \ /
  Last update: 2019-12-11 16:51    [W:0.066 / U:1.448 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site