aboutsummaryrefslogtreecommitdiffstats
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
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>
-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