aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/core/Makefile2
-rw-r--r--drivers/usb/core/hcd.c2
-rw-r--r--drivers/usb/core/hub.c3
-rw-r--r--drivers/usb/core/notify.c120
-rw-r--r--drivers/usb/core/usb.h6
-rw-r--r--include/linux/usb.h8
6 files changed, 140 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
5usbcore-objs := usb.o hub.o hcd.o urb.o message.o \ 5usbcore-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
8ifeq ($(CONFIG_PCI),y) 8ifeq ($(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
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}
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 */
84extern void usb_notify_add_device(struct usb_device *udev);
85extern void usb_notify_remove_device(struct usb_device *udev);
86extern void usb_notify_add_bus(struct usb_bus *ubus);
87extern void usb_notify_remove_bus(struct usb_bus *ubus);
88
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 207b1ad9d990..a2d923fd54f9 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -1135,6 +1135,14 @@ usb_maxpacket(struct usb_device *udev, int pipe, int is_out)
1135 1135
1136/* -------------------------------------------------------------------------- */ 1136/* -------------------------------------------------------------------------- */
1137 1137
1138/* Events from the usb core */
1139#define USB_DEVICE_ADD 0x0001
1140#define USB_DEVICE_REMOVE 0x0002
1141#define USB_BUS_ADD 0x0003
1142#define USB_BUS_REMOVE 0x0004
1143extern void usb_register_notify(struct notifier_block *nb);
1144extern void usb_unregister_notify(struct notifier_block *nb);
1145
1138#ifdef DEBUG 1146#ifdef DEBUG
1139#define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , __FILE__ , ## arg) 1147#define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , __FILE__ , ## arg)
1140#else 1148#else