aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenrique de Moraes Holschuh <hmh@hmh.eng.br>2008-06-23 16:23:03 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-06-26 14:21:21 -0400
commit79399a8d1908f6a406e82d23c5a9937e1722ed3a (patch)
tree2eb7cfc13959917114b745e4a0bff2810df1c870
parent526324b61a9667ed9a71f0a8a8899cf675346c76 (diff)
rfkill: add notifier chains support
Add a notifier chain for use by the rfkill class. This notifier chain signals the following events (more to be added when needed): 1. rfkill: rfkill device state has changed A pointer to the rfkill struct will be passed as a parameter. The notifier message types have been added to include/linux/rfkill.h instead of to include/linux/notifier.h in order to avoid the madness of modifying a header used globally (and that triggers an almost full tree rebuild every time it is touched) with information that is of interest only to code that includes the rfkill.h header. Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br> Acked-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--include/linux/rfkill.h7
-rw-r--r--net/rfkill/rfkill.c70
2 files changed, 74 insertions, 3 deletions
diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h
index c0cab7d37828..98667becdee4 100644
--- a/include/linux/rfkill.h
+++ b/include/linux/rfkill.h
@@ -117,4 +117,11 @@ static inline char *rfkill_get_led_name(struct rfkill *rfkill)
117#endif 117#endif
118} 118}
119 119
120/* rfkill notification chain */
121#define RFKILL_STATE_CHANGED 0x0001 /* state of a normal rfkill
122 switch has changed */
123
124int register_rfkill_notifier(struct notifier_block *nb);
125int unregister_rfkill_notifier(struct notifier_block *nb);
126
120#endif /* RFKILL_H */ 127#endif /* RFKILL_H */
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c
index fb566902030a..a561e350a70a 100644
--- a/net/rfkill/rfkill.c
+++ b/net/rfkill/rfkill.c
@@ -46,6 +46,49 @@ MODULE_PARM_DESC(default_state,
46 46
47static enum rfkill_state rfkill_states[RFKILL_TYPE_MAX]; 47static enum rfkill_state rfkill_states[RFKILL_TYPE_MAX];
48 48
49static BLOCKING_NOTIFIER_HEAD(rfkill_notifier_list);
50
51
52/**
53 * register_rfkill_notifier - Add notifier to rfkill notifier chain
54 * @nb: pointer to the new entry to add to the chain
55 *
56 * See blocking_notifier_chain_register() for return value and further
57 * observations.
58 *
59 * Adds a notifier to the rfkill notifier chain. The chain will be
60 * called with a pointer to the relevant rfkill structure as a parameter,
61 * refer to include/linux/rfkill.h for the possible events.
62 *
63 * Notifiers added to this chain are to always return NOTIFY_DONE. This
64 * chain is a blocking notifier chain: notifiers can sleep.
65 *
66 * Calls to this chain may have been done through a workqueue. One must
67 * assume unordered asynchronous behaviour, there is no way to know if
68 * actions related to the event that generated the notification have been
69 * carried out already.
70 */
71int register_rfkill_notifier(struct notifier_block *nb)
72{
73 return blocking_notifier_chain_register(&rfkill_notifier_list, nb);
74}
75EXPORT_SYMBOL_GPL(register_rfkill_notifier);
76
77/**
78 * unregister_rfkill_notifier - remove notifier from rfkill notifier chain
79 * @nb: pointer to the entry to remove from the chain
80 *
81 * See blocking_notifier_chain_unregister() for return value and further
82 * observations.
83 *
84 * Removes a notifier from the rfkill notifier chain.
85 */
86int unregister_rfkill_notifier(struct notifier_block *nb)
87{
88 return blocking_notifier_chain_unregister(&rfkill_notifier_list, nb);
89}
90EXPORT_SYMBOL_GPL(unregister_rfkill_notifier);
91
49 92
50static void rfkill_led_trigger(struct rfkill *rfkill, 93static void rfkill_led_trigger(struct rfkill *rfkill,
51 enum rfkill_state state) 94 enum rfkill_state state)
@@ -62,14 +105,25 @@ static void rfkill_led_trigger(struct rfkill *rfkill,
62#endif /* CONFIG_RFKILL_LEDS */ 105#endif /* CONFIG_RFKILL_LEDS */
63} 106}
64 107
108static void notify_rfkill_state_change(struct rfkill *rfkill)
109{
110 blocking_notifier_call_chain(&rfkill_notifier_list,
111 RFKILL_STATE_CHANGED,
112 rfkill);
113}
114
65static void update_rfkill_state(struct rfkill *rfkill) 115static void update_rfkill_state(struct rfkill *rfkill)
66{ 116{
67 enum rfkill_state newstate; 117 enum rfkill_state newstate, oldstate;
68 118
69 if (rfkill->get_state) { 119 if (rfkill->get_state) {
70 mutex_lock(&rfkill->mutex); 120 mutex_lock(&rfkill->mutex);
71 if (!rfkill->get_state(rfkill->data, &newstate)) 121 if (!rfkill->get_state(rfkill->data, &newstate)) {
122 oldstate = rfkill->state;
72 rfkill->state = newstate; 123 rfkill->state = newstate;
124 if (oldstate != newstate)
125 notify_rfkill_state_change(rfkill);
126 }
73 mutex_unlock(&rfkill->mutex); 127 mutex_unlock(&rfkill->mutex);
74 } 128 }
75} 129}
@@ -93,8 +147,10 @@ static int rfkill_toggle_radio(struct rfkill *rfkill,
93 rfkill->state = state; 147 rfkill->state = state;
94 } 148 }
95 149
96 if (force || rfkill->state != oldstate) 150 if (force || rfkill->state != oldstate) {
97 rfkill_led_trigger(rfkill, rfkill->state); 151 rfkill_led_trigger(rfkill, rfkill->state);
152 notify_rfkill_state_change(rfkill);
153 }
98 154
99 return retval; 155 return retval;
100} 156}
@@ -139,12 +195,20 @@ EXPORT_SYMBOL(rfkill_switch_all);
139 */ 195 */
140int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state) 196int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state)
141{ 197{
198 enum rfkill_state oldstate;
199
142 if (state != RFKILL_STATE_OFF && 200 if (state != RFKILL_STATE_OFF &&
143 state != RFKILL_STATE_ON) 201 state != RFKILL_STATE_ON)
144 return -EINVAL; 202 return -EINVAL;
145 203
146 mutex_lock(&rfkill->mutex); 204 mutex_lock(&rfkill->mutex);
205
206 oldstate = rfkill->state;
147 rfkill->state = state; 207 rfkill->state = state;
208
209 if (state != oldstate)
210 notify_rfkill_state_change(rfkill);
211
148 mutex_unlock(&rfkill->mutex); 212 mutex_unlock(&rfkill->mutex);
149 213
150 return 0; 214 return 0;