aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/notify.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2005-06-21 00:15:16 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-10-28 19:47:46 -0400
commit3099e75a7ccc3c5b0a4cf988a76d9c4a7fa5e91a (patch)
tree8b1e7e5ddf097b347717e64aefb14ab33c9b2f90 /drivers/usb/core/notify.c
parent4592bf5a22593704bb9e8c584a81bf6ca4f6cfec (diff)
[PATCH] USB: add notifier functions to the USB core for devices and busses
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>
Diffstat (limited to 'drivers/usb/core/notify.c')
-rw-r--r--drivers/usb/core/notify.c120
1 files changed, 120 insertions, 0 deletions
diff --git a/drivers/usb/core/notify.c b/drivers/usb/core/notify.c
new file mode 100644
index 000000000000..37da059eced7
--- /dev/null
+++ b/drivers/usb/core/notify.c
@@ -0,0 +1,120 @@
1/*
2 * All the USB notify logic
3 *
4 * (C) Copyright 2005 Greg Kroah-Hartman <gregkh@suse.de>
5 *
6 * notifier functions originally based on those in kernel/sys.c
7 * but fixed up to not be so broken.
8 *
9 */
10
11
12#include <linux/config.h>
13#include <linux/kernel.h>
14#include <linux/notifier.h>
15#ifdef CONFIG_USB_DEBUG
16 #define DEBUG
17#else
18 #undef DEBUG
19#endif
20#include <linux/usb.h>
21
22#include "usb.h"
23
24
25static struct notifier_block *usb_notifier_list;
26static DECLARE_MUTEX(usb_notifier_lock);
27
28static void usb_notifier_chain_register(struct notifier_block **list,
29 struct notifier_block *n)
30{
31 down(&usb_notifier_lock);
32 while (*list) {
33 if (n->priority > (*list)->priority)
34 break;
35 list = &((*list)->next);
36 }
37 n->next = *list;
38 *list = n;
39 up(&usb_notifier_lock);
40}
41
42static void usb_notifier_chain_unregister(struct notifier_block **nl,
43 struct notifier_block *n)
44{
45 down(&usb_notifier_lock);
46 while ((*nl)!=NULL) {
47 if ((*nl)==n) {
48 *nl = n->next;
49 goto exit;
50 }
51 nl=&((*nl)->next);
52 }
53exit:
54 up(&usb_notifier_lock);
55}
56
57static int usb_notifier_call_chain(struct notifier_block **n,
58 unsigned long val, void *v)
59{
60 int ret=NOTIFY_DONE;
61 struct notifier_block *nb = *n;
62
63 down(&usb_notifier_lock);
64 while (nb) {
65 ret = nb->notifier_call(nb,val,v);
66 if (ret&NOTIFY_STOP_MASK) {
67 goto exit;
68 }
69 nb = nb->next;
70 }
71exit:
72 up(&usb_notifier_lock);
73 return ret;
74}
75
76/**
77 * usb_register_notify - register a notifier callback whenever a usb change happens
78 * @nb: pointer to the notifier block for the callback events.
79 *
80 * These changes are either USB devices or busses being added or removed.
81 */
82void usb_register_notify(struct notifier_block *nb)
83{
84 usb_notifier_chain_register(&usb_notifier_list, nb);
85}
86EXPORT_SYMBOL_GPL(usb_register_notify);
87
88/**
89 * usb_unregister_notify - unregister a notifier callback
90 * @nb: pointer to the notifier block for the callback events.
91 *
92 * usb_register_notifier() must have been previously called for this function
93 * to work properly.
94 */
95void usb_unregister_notify(struct notifier_block *nb)
96{
97 usb_notifier_chain_unregister(&usb_notifier_list, nb);
98}
99EXPORT_SYMBOL_GPL(usb_unregister_notify);
100
101
102void usb_notify_add_device(struct usb_device *udev)
103{
104 usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_ADD, udev);
105}
106
107void usb_notify_remove_device(struct usb_device *udev)
108{
109 usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_REMOVE, udev);
110}
111
112void usb_notify_add_bus(struct usb_bus *ubus)
113{
114 usb_notifier_call_chain(&usb_notifier_list, USB_BUS_ADD, ubus);
115}
116
117void usb_notify_remove_bus(struct usb_bus *ubus)
118{
119 usb_notifier_call_chain(&usb_notifier_list, USB_BUS_REMOVE, ubus);
120}