[PATCH v2 2/3] usb: roles: Add API to register notifiers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxxxxx>
---

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




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux