[PATCH] USB: add notifier functions to the USB core for devices and busses
authorGreg Kroah-Hartman <gregkh@suse.de>
Tue, 21 Jun 2005 04:15:16 +0000 (21:15 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 28 Oct 2005 23:47:46 +0000 (16:47 -0700)
This should let us get rid of all of the different hooks in the USB core for
when something has changed.

Also, some other parts of the kernel have wanted to know this kind of
information at times.

Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/core/Makefile
drivers/usb/core/hcd.c
drivers/usb/core/hub.c
drivers/usb/core/notify.c [new file with mode: 0644]
drivers/usb/core/usb.h
include/linux/usb.h

index d5503cf0bf74c8586a5d7ed66b029014ec4b6d1f..dd1c4d2a0c3122bdca2776e78e1bd2667288abe7 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 usbcore-objs   := usb.o hub.o hcd.o urb.o message.o \
-                       config.o file.o buffer.o sysfs.o devio.o
+                       config.o file.o buffer.o sysfs.o devio.o notify.o
 
 ifeq ($(CONFIG_PCI),y)
        usbcore-objs    += hcd-pci.o
index 9ad3912a5ed77bee17daeb7352c5685789c364e3..b700b6cdb683f0258430e4af1570e6caf02fcce8 100644 (file)
@@ -792,6 +792,7 @@ static int usb_register_bus(struct usb_bus *bus)
        list_add (&bus->bus_list, &usb_bus_list);
        up (&usb_bus_list_lock);
 
+       usb_notify_add_bus(bus);
        usbfs_add_bus (bus);
        usbmon_notify_bus_add (bus);
 
@@ -820,6 +821,7 @@ static void usb_deregister_bus (struct usb_bus *bus)
        list_del (&bus->bus_list);
        up (&usb_bus_list_lock);
 
+       usb_notify_remove_bus(bus);
        usbmon_notify_bus_remove (bus);
        usbfs_remove_bus (bus);
 
index 273e6ccca213823ca3d8922b3763ecb060e58f13..4f1a8c8cf92bea7baeb4407f0d4cf94442f5c843 100644 (file)
@@ -1128,6 +1128,8 @@ void usb_disconnect(struct usb_device **pdev)
         */
        usb_disable_device(udev, 0);
 
+       usb_notify_remove_device(udev);
+
        /* Free the device number, remove the /proc/bus/usb entry and
         * the sysfs attributes, and delete the parent's children[]
         * (or root_hub) pointer.
@@ -1371,6 +1373,7 @@ int usb_new_device(struct usb_device *udev)
        }
 
        /* USB device state == configured ... usable */
+       usb_notify_add_device(udev);
 
        /* add a /proc/bus/usb entry */
        usbdev_add(udev);
diff --git a/drivers/usb/core/notify.c b/drivers/usb/core/notify.c
new file mode 100644 (file)
index 0000000..37da059
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * All the USB notify logic
+ *
+ * (C) Copyright 2005 Greg Kroah-Hartman <gregkh@suse.de>
+ *
+ * notifier functions originally based on those in kernel/sys.c
+ * but fixed up to not be so broken.
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/notifier.h>
+#ifdef CONFIG_USB_DEBUG
+       #define DEBUG
+#else
+       #undef DEBUG
+#endif
+#include <linux/usb.h>
+
+#include "usb.h"
+
+
+static struct notifier_block *usb_notifier_list;
+static DECLARE_MUTEX(usb_notifier_lock);
+
+static void usb_notifier_chain_register(struct notifier_block **list,
+                                       struct notifier_block *n)
+{
+       down(&usb_notifier_lock);
+       while (*list) {
+               if (n->priority > (*list)->priority)
+                       break;
+               list = &((*list)->next);
+       }
+       n->next = *list;
+       *list = n;
+       up(&usb_notifier_lock);
+}
+
+static void usb_notifier_chain_unregister(struct notifier_block **nl,
+                                  struct notifier_block *n)
+{
+       down(&usb_notifier_lock);
+       while ((*nl)!=NULL) {
+               if ((*nl)==n) {
+                       *nl = n->next;
+                       goto exit;
+               }
+               nl=&((*nl)->next);
+       }
+exit:
+       up(&usb_notifier_lock);
+}
+
+static int usb_notifier_call_chain(struct notifier_block **n,
+                                  unsigned long val, void *v)
+{
+       int ret=NOTIFY_DONE;
+       struct notifier_block *nb = *n;
+
+       down(&usb_notifier_lock);
+       while (nb) {
+               ret = nb->notifier_call(nb,val,v);
+               if (ret&NOTIFY_STOP_MASK) {
+                       goto exit;
+               }
+               nb = nb->next;
+       }
+exit:
+       up(&usb_notifier_lock);
+       return ret;
+}
+
+/**
+ * usb_register_notify - register a notifier callback whenever a usb change happens
+ * @nb: pointer to the notifier block for the callback events.
+ *
+ * These changes are either USB devices or busses being added or removed.
+ */
+void usb_register_notify(struct notifier_block *nb)
+{
+       usb_notifier_chain_register(&usb_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(usb_register_notify);
+
+/**
+ * usb_unregister_notify - unregister a notifier callback
+ * @nb: pointer to the notifier block for the callback events.
+ *
+ * usb_register_notifier() must have been previously called for this function
+ * to work properly.
+ */
+void usb_unregister_notify(struct notifier_block *nb)
+{
+       usb_notifier_chain_unregister(&usb_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(usb_unregister_notify);
+
+
+void usb_notify_add_device(struct usb_device *udev)
+{
+       usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_ADD, udev);
+}
+
+void usb_notify_remove_device(struct usb_device *udev)
+{
+       usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_REMOVE, udev);
+}
+
+void usb_notify_add_bus(struct usb_bus *ubus)
+{
+       usb_notifier_call_chain(&usb_notifier_list, USB_BUS_ADD, ubus);
+}
+
+void usb_notify_remove_bus(struct usb_bus *ubus)
+{
+       usb_notifier_call_chain(&usb_notifier_list, USB_BUS_REMOVE, ubus);
+}
index 3dc8096c0f92d0f85c2ed245b88daecc8342329a..811cf4482e0d2e2cb34f082c14cce8f8624cb841 100644 (file)
@@ -80,3 +80,9 @@ struct dev_state {
        unsigned long ifclaimed;
 };
 
+/* internal notify stuff */
+extern void usb_notify_add_device(struct usb_device *udev);
+extern void usb_notify_remove_device(struct usb_device *udev);
+extern void usb_notify_add_bus(struct usb_bus *ubus);
+extern void usb_notify_remove_bus(struct usb_bus *ubus);
+
index 207b1ad9d990b9abb1582cf6c8c4be69d732680e..a2d923fd54f94769b1603fc0dbca289eac7a826b 100644 (file)
@@ -1135,6 +1135,14 @@ usb_maxpacket(struct usb_device *udev, int pipe, int is_out)
 
 /* -------------------------------------------------------------------------- */
 
+/* Events from the usb core */
+#define USB_DEVICE_ADD         0x0001
+#define USB_DEVICE_REMOVE      0x0002
+#define USB_BUS_ADD            0x0003
+#define USB_BUS_REMOVE         0x0004
+extern void usb_register_notify(struct notifier_block *nb);
+extern void usb_unregister_notify(struct notifier_block *nb);
+
 #ifdef DEBUG
 #define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , __FILE__ , ## arg)
 #else