diff options
author | Paul Mackerras <paulus@samba.org> | 2005-10-30 21:37:12 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2005-10-30 21:37:12 -0500 |
commit | 23fd07750a789a66fe88cf173d52a18f1a387da4 (patch) | |
tree | 06fdd6df35fdb835abdaa9b754d62f6b84b97250 /drivers/usb/core/notify.c | |
parent | bd787d438a59266af3c9f6351644c85ef1dd21fe (diff) | |
parent | ed28f96ac1960f30f818374d65be71d2fdf811b0 (diff) |
Merge ../linux-2.6 by hand
Diffstat (limited to 'drivers/usb/core/notify.c')
-rw-r--r-- | drivers/usb/core/notify.c | 120 |
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 | |||
25 | static struct notifier_block *usb_notifier_list; | ||
26 | static DECLARE_MUTEX(usb_notifier_lock); | ||
27 | |||
28 | static 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 | |||
42 | static 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 | } | ||
53 | exit: | ||
54 | up(&usb_notifier_lock); | ||
55 | } | ||
56 | |||
57 | static 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 | } | ||
71 | exit: | ||
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 | */ | ||
82 | void usb_register_notify(struct notifier_block *nb) | ||
83 | { | ||
84 | usb_notifier_chain_register(&usb_notifier_list, nb); | ||
85 | } | ||
86 | EXPORT_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 | */ | ||
95 | void usb_unregister_notify(struct notifier_block *nb) | ||
96 | { | ||
97 | usb_notifier_chain_unregister(&usb_notifier_list, nb); | ||
98 | } | ||
99 | EXPORT_SYMBOL_GPL(usb_unregister_notify); | ||
100 | |||
101 | |||
102 | void usb_notify_add_device(struct usb_device *udev) | ||
103 | { | ||
104 | usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_ADD, udev); | ||
105 | } | ||
106 | |||
107 | void usb_notify_remove_device(struct usb_device *udev) | ||
108 | { | ||
109 | usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_REMOVE, udev); | ||
110 | } | ||
111 | |||
112 | void usb_notify_add_bus(struct usb_bus *ubus) | ||
113 | { | ||
114 | usb_notifier_call_chain(&usb_notifier_list, USB_BUS_ADD, ubus); | ||
115 | } | ||
116 | |||
117 | void usb_notify_remove_bus(struct usb_bus *ubus) | ||
118 | { | ||
119 | usb_notifier_call_chain(&usb_notifier_list, USB_BUS_REMOVE, ubus); | ||
120 | } | ||