diff options
Diffstat (limited to 'drivers/usb/core')
-rw-r--r-- | drivers/usb/core/Makefile | 2 | ||||
-rw-r--r-- | drivers/usb/core/hcd.c | 2 | ||||
-rw-r--r-- | drivers/usb/core/hub.c | 3 | ||||
-rw-r--r-- | drivers/usb/core/notify.c | 120 | ||||
-rw-r--r-- | drivers/usb/core/usb.h | 6 |
5 files changed, 132 insertions, 1 deletions
diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile index d5503cf0bf74..dd1c4d2a0c31 100644 --- a/drivers/usb/core/Makefile +++ b/drivers/usb/core/Makefile | |||
@@ -3,7 +3,7 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | usbcore-objs := usb.o hub.o hcd.o urb.o message.o \ | 5 | usbcore-objs := usb.o hub.o hcd.o urb.o message.o \ |
6 | config.o file.o buffer.o sysfs.o devio.o | 6 | config.o file.o buffer.o sysfs.o devio.o notify.o |
7 | 7 | ||
8 | ifeq ($(CONFIG_PCI),y) | 8 | ifeq ($(CONFIG_PCI),y) |
9 | usbcore-objs += hcd-pci.o | 9 | usbcore-objs += hcd-pci.o |
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 9ad3912a5ed7..b700b6cdb683 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -792,6 +792,7 @@ static int usb_register_bus(struct usb_bus *bus) | |||
792 | list_add (&bus->bus_list, &usb_bus_list); | 792 | list_add (&bus->bus_list, &usb_bus_list); |
793 | up (&usb_bus_list_lock); | 793 | up (&usb_bus_list_lock); |
794 | 794 | ||
795 | usb_notify_add_bus(bus); | ||
795 | usbfs_add_bus (bus); | 796 | usbfs_add_bus (bus); |
796 | usbmon_notify_bus_add (bus); | 797 | usbmon_notify_bus_add (bus); |
797 | 798 | ||
@@ -820,6 +821,7 @@ static void usb_deregister_bus (struct usb_bus *bus) | |||
820 | list_del (&bus->bus_list); | 821 | list_del (&bus->bus_list); |
821 | up (&usb_bus_list_lock); | 822 | up (&usb_bus_list_lock); |
822 | 823 | ||
824 | usb_notify_remove_bus(bus); | ||
823 | usbmon_notify_bus_remove (bus); | 825 | usbmon_notify_bus_remove (bus); |
824 | usbfs_remove_bus (bus); | 826 | usbfs_remove_bus (bus); |
825 | 827 | ||
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 273e6ccca213..4f1a8c8cf92b 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -1128,6 +1128,8 @@ void usb_disconnect(struct usb_device **pdev) | |||
1128 | */ | 1128 | */ |
1129 | usb_disable_device(udev, 0); | 1129 | usb_disable_device(udev, 0); |
1130 | 1130 | ||
1131 | usb_notify_remove_device(udev); | ||
1132 | |||
1131 | /* Free the device number, remove the /proc/bus/usb entry and | 1133 | /* Free the device number, remove the /proc/bus/usb entry and |
1132 | * the sysfs attributes, and delete the parent's children[] | 1134 | * the sysfs attributes, and delete the parent's children[] |
1133 | * (or root_hub) pointer. | 1135 | * (or root_hub) pointer. |
@@ -1371,6 +1373,7 @@ int usb_new_device(struct usb_device *udev) | |||
1371 | } | 1373 | } |
1372 | 1374 | ||
1373 | /* USB device state == configured ... usable */ | 1375 | /* USB device state == configured ... usable */ |
1376 | usb_notify_add_device(udev); | ||
1374 | 1377 | ||
1375 | /* add a /proc/bus/usb entry */ | 1378 | /* add a /proc/bus/usb entry */ |
1376 | usbdev_add(udev); | 1379 | usbdev_add(udev); |
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 | } | ||
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 3dc8096c0f92..811cf4482e0d 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h | |||
@@ -80,3 +80,9 @@ struct dev_state { | |||
80 | unsigned long ifclaimed; | 80 | unsigned long ifclaimed; |
81 | }; | 81 | }; |
82 | 82 | ||
83 | /* internal notify stuff */ | ||
84 | extern void usb_notify_add_device(struct usb_device *udev); | ||
85 | extern void usb_notify_remove_device(struct usb_device *udev); | ||
86 | extern void usb_notify_add_bus(struct usb_bus *ubus); | ||
87 | extern void usb_notify_remove_bus(struct usb_bus *ubus); | ||
88 | |||