xref: /linux/drivers/usb/core/notify.c (revision 858259cf7d1c443c836a2022b78cb281f0a9b95e)
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 }
121