3 * RF-kill framework integration
6 * Copyright (C) 2008 Intel Corporation <linux-wimax@intel.com>
7 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License version
11 * 2 as published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 * This integrates into the Linux Kernel rfkill susbystem so that the
25 * drivers just have to do the bare minimal work, which is providing a
26 * method to set the software RF-Kill switch and to report changes in
27 * the software and hardware switch status.
29 * A non-polled generic rfkill device is embedded into the WiMAX
30 * subsystem's representation of a device.
32 * FIXME: Need polled support? use a timer or add the implementation
35 * All device drivers have to do is after wimax_dev_init(), call
36 * wimax_report_rfkill_hw() and wimax_report_rfkill_sw() to update
37 * initial state and then every time it changes. See wimax.h:struct
38 * wimax_dev for more information.
42 * wimax_gnl_doit_rfkill() User space calling wimax_rfkill()
43 * wimax_rfkill() Kernel calling wimax_rfkill()
44 * __wimax_rf_toggle_radio()
46 * wimax_rfkill_toggle_radio() RF-Kill subsytem calling
47 * __wimax_rf_toggle_radio()
49 * __wimax_rf_toggle_radio()
50 * wimax_dev->op_rfkill_sw_toggle() Driver backend
51 * __wimax_state_change()
53 * wimax_report_rfkill_sw() Driver reports state change
54 * __wimax_state_change()
56 * wimax_report_rfkill_hw() Driver reports state change
57 * __wimax_state_change()
59 * wimax_rfkill_add() Initialize/shutdown rfkill support
60 * wimax_rfkill_rm() [called by wimax_dev_add/rm()]
63 #include <net/wimax.h>
64 #include <net/genetlink.h>
65 #include <linux/wimax.h>
66 #include <linux/security.h>
67 #include <linux/rfkill.h>
68 #include <linux/input.h>
69 #include "wimax-internal.h"
71 #define D_SUBMODULE op_rfkill
72 #include "debug-levels.h"
74 #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
78 * wimax_report_rfkill_hw - Reports changes in the hardware RF switch
80 * @wimax_dev: WiMAX device descriptor
82 * @state: New state of the RF Kill switch. %WIMAX_RF_ON radio on,
83 * %WIMAX_RF_OFF radio off.
85 * When the device detects a change in the state of thehardware RF
86 * switch, it must call this function to let the WiMAX kernel stack
87 * know that the state has changed so it can be properly propagated.
89 * The WiMAX stack caches the state (the driver doesn't need to). As
90 * well, as the change is propagated it will come back as a request to
91 * change the software state to mirror the hardware state.
93 * If the device doesn't have a hardware kill switch, just report
94 * it on initialization as always on (%WIMAX_RF_ON, radio on).
96 void wimax_report_rfkill_hw(struct wimax_dev *wimax_dev,
97 enum wimax_rf_state state)
100 struct device *dev = wimax_dev_to_dev(wimax_dev);
101 enum wimax_st wimax_state;
102 enum rfkill_state rfkill_state;
104 d_fnstart(3, dev, "(wimax_dev %p state %u)\n", wimax_dev, state);
105 BUG_ON(state == WIMAX_RF_QUERY);
106 BUG_ON(state != WIMAX_RF_ON && state != WIMAX_RF_OFF);
108 mutex_lock(&wimax_dev->mutex);
109 result = wimax_dev_is_ready(wimax_dev);
111 goto error_not_ready;
113 if (state != wimax_dev->rf_hw) {
114 wimax_dev->rf_hw = state;
115 rfkill_state = state == WIMAX_RF_ON ?
116 RFKILL_STATE_OFF : RFKILL_STATE_ON;
117 if (wimax_dev->rf_hw == WIMAX_RF_ON
118 && wimax_dev->rf_sw == WIMAX_RF_ON)
119 wimax_state = WIMAX_ST_READY;
121 wimax_state = WIMAX_ST_RADIO_OFF;
122 __wimax_state_change(wimax_dev, wimax_state);
123 input_report_key(wimax_dev->rfkill_input, KEY_WIMAX,
127 mutex_unlock(&wimax_dev->mutex);
128 d_fnend(3, dev, "(wimax_dev %p state %u) = void [%d]\n",
129 wimax_dev, state, result);
131 EXPORT_SYMBOL_GPL(wimax_report_rfkill_hw);
135 * wimax_report_rfkill_sw - Reports changes in the software RF switch
137 * @wimax_dev: WiMAX device descriptor
139 * @state: New state of the RF kill switch. %WIMAX_RF_ON radio on,
140 * %WIMAX_RF_OFF radio off.
142 * Reports changes in the software RF switch state to the the WiMAX
145 * The main use is during initialization, so the driver can query the
146 * device for its current software radio kill switch state and feed it
149 * On the side, the device does not change the software state by
150 * itself. In practice, this can happen, as the device might decide to
151 * switch (in software) the radio off for different reasons.
153 void wimax_report_rfkill_sw(struct wimax_dev *wimax_dev,
154 enum wimax_rf_state state)
157 struct device *dev = wimax_dev_to_dev(wimax_dev);
158 enum wimax_st wimax_state;
160 d_fnstart(3, dev, "(wimax_dev %p state %u)\n", wimax_dev, state);
161 BUG_ON(state == WIMAX_RF_QUERY);
162 BUG_ON(state != WIMAX_RF_ON && state != WIMAX_RF_OFF);
164 mutex_lock(&wimax_dev->mutex);
165 result = wimax_dev_is_ready(wimax_dev);
167 goto error_not_ready;
169 if (state != wimax_dev->rf_sw) {
170 wimax_dev->rf_sw = state;
171 if (wimax_dev->rf_hw == WIMAX_RF_ON
172 && wimax_dev->rf_sw == WIMAX_RF_ON)
173 wimax_state = WIMAX_ST_READY;
175 wimax_state = WIMAX_ST_RADIO_OFF;
176 __wimax_state_change(wimax_dev, wimax_state);
179 mutex_unlock(&wimax_dev->mutex);
180 d_fnend(3, dev, "(wimax_dev %p state %u) = void [%d]\n",
181 wimax_dev, state, result);
183 EXPORT_SYMBOL_GPL(wimax_report_rfkill_sw);
187 * Callback for the RF Kill toggle operation
189 * This function is called by:
191 * - The rfkill subsystem when the RF-Kill key is pressed in the
192 * hardware and the driver notifies through
193 * wimax_report_rfkill_hw(). The rfkill subsystem ends up calling back
194 * here so the software RF Kill switch state is changed to reflect
195 * the hardware switch state.
197 * - When the user sets the state through sysfs' rfkill/state file
199 * - When the user calls wimax_rfkill().
203 * WARNING! When we call rfkill_unregister(), this will be called with
206 * WARNING: wimax_dev must be locked
209 int __wimax_rf_toggle_radio(struct wimax_dev *wimax_dev,
210 enum wimax_rf_state state)
213 struct device *dev = wimax_dev_to_dev(wimax_dev);
214 enum wimax_st wimax_state;
217 d_fnstart(3, dev, "(wimax_dev %p state %u)\n", wimax_dev, state);
218 if (wimax_dev->rf_sw == state)
220 if (wimax_dev->op_rfkill_sw_toggle != NULL)
221 result = wimax_dev->op_rfkill_sw_toggle(wimax_dev, state);
222 else if (state == WIMAX_RF_OFF) /* No op? can't turn off */
224 else /* No op? can turn on */
225 result = 0; /* should never happen tho */
228 wimax_dev->rf_sw = state;
229 wimax_state = state == WIMAX_RF_ON ?
230 WIMAX_ST_READY : WIMAX_ST_RADIO_OFF;
231 __wimax_state_change(wimax_dev, wimax_state);
234 d_fnend(3, dev, "(wimax_dev %p state %u) = %d\n",
235 wimax_dev, state, result);
241 * Translate from rfkill state to wimax state
243 * NOTE: Special state handling rules here
245 * Just pretend the call didn't happen if we are in a state where
246 * we know for sure it cannot be handled (WIMAX_ST_DOWN or
247 * __WIMAX_ST_QUIESCING). rfkill() needs it to register and
248 * unregister, as it will run this path.
250 * NOTE: This call will block until the operation is completed.
253 int wimax_rfkill_toggle_radio(void *data, enum rfkill_state state)
256 struct wimax_dev *wimax_dev = data;
257 struct device *dev = wimax_dev_to_dev(wimax_dev);
258 enum wimax_rf_state rf_state;
260 d_fnstart(3, dev, "(wimax_dev %p state %u)\n", wimax_dev, state);
262 case RFKILL_STATE_ON:
263 rf_state = WIMAX_RF_OFF;
265 case RFKILL_STATE_OFF:
266 rf_state = WIMAX_RF_ON;
271 mutex_lock(&wimax_dev->mutex);
272 if (wimax_dev->state <= __WIMAX_ST_QUIESCING)
273 result = 0; /* just pretend it didn't happen */
275 result = __wimax_rf_toggle_radio(wimax_dev, rf_state);
276 mutex_unlock(&wimax_dev->mutex);
277 d_fnend(3, dev, "(wimax_dev %p state %u) = %d\n",
278 wimax_dev, state, result);
284 * wimax_rfkill - Set the software RF switch state for a WiMAX device
286 * @wimax_dev: WiMAX device descriptor
288 * @state: New RF state.
292 * >= 0 toggle state if ok, < 0 errno code on error. The toggle state
293 * is returned as a bitmap, bit 0 being the hardware RF state, bit 1
294 * the software RF state.
296 * 0 means disabled (%WIMAX_RF_ON, radio on), 1 means enabled radio
297 * off (%WIMAX_RF_OFF).
301 * Called by the user when he wants to request the WiMAX radio to be
302 * switched on (%WIMAX_RF_ON) or off (%WIMAX_RF_OFF). With
303 * %WIMAX_RF_QUERY, just the current state is returned.
307 * This call will block until the operation is complete.
309 int wimax_rfkill(struct wimax_dev *wimax_dev, enum wimax_rf_state state)
312 struct device *dev = wimax_dev_to_dev(wimax_dev);
314 d_fnstart(3, dev, "(wimax_dev %p state %u)\n", wimax_dev, state);
315 mutex_lock(&wimax_dev->mutex);
316 result = wimax_dev_is_ready(wimax_dev);
318 goto error_not_ready;
322 result = __wimax_rf_toggle_radio(wimax_dev, state);
332 result = wimax_dev->rf_sw << 1 | wimax_dev->rf_hw;
335 mutex_unlock(&wimax_dev->mutex);
336 d_fnend(3, dev, "(wimax_dev %p state %u) = %d\n",
337 wimax_dev, state, result);
340 EXPORT_SYMBOL(wimax_rfkill);
344 * Register a new WiMAX device's RF Kill support
346 * WARNING: wimax_dev->mutex must be unlocked
348 int wimax_rfkill_add(struct wimax_dev *wimax_dev)
351 struct rfkill *rfkill;
352 struct input_dev *input_dev;
353 struct device *dev = wimax_dev_to_dev(wimax_dev);
355 d_fnstart(3, dev, "(wimax_dev %p)\n", wimax_dev);
356 /* Initialize RF Kill */
358 rfkill = rfkill_allocate(dev, RFKILL_TYPE_WIMAX);
360 goto error_rfkill_allocate;
361 wimax_dev->rfkill = rfkill;
363 rfkill->name = wimax_dev->name;
364 rfkill->state = RFKILL_STATE_OFF;
365 rfkill->data = wimax_dev;
366 rfkill->toggle_radio = wimax_rfkill_toggle_radio;
367 rfkill->user_claim_unsupported = 1;
369 /* Initialize the input device for the hw key */
370 input_dev = input_allocate_device();
371 if (input_dev == NULL)
372 goto error_input_allocate;
373 wimax_dev->rfkill_input = input_dev;
374 d_printf(1, dev, "rfkill %p input %p\n", rfkill, input_dev);
376 input_dev->name = wimax_dev->name;
377 /* FIXME: get a real device bus ID and stuff? do we care? */
378 input_dev->id.bustype = BUS_HOST;
379 input_dev->id.vendor = 0xffff;
380 input_dev->evbit[0] = BIT(EV_KEY);
381 set_bit(KEY_WIMAX, input_dev->keybit);
384 result = input_register_device(wimax_dev->rfkill_input);
386 goto error_input_register;
387 result = rfkill_register(wimax_dev->rfkill);
389 goto error_rfkill_register;
391 /* If there is no SW toggle op, SW RFKill is always on */
392 if (wimax_dev->op_rfkill_sw_toggle == NULL)
393 wimax_dev->rf_sw = WIMAX_RF_ON;
395 d_fnend(3, dev, "(wimax_dev %p) = 0\n", wimax_dev);
398 /* if rfkill_register() suceeds, can't use rfkill_free() any
399 * more, only rfkill_unregister() [it owns the refcount]; with
400 * the input device we have the same issue--hence the if. */
401 error_rfkill_register:
402 input_unregister_device(wimax_dev->rfkill_input);
403 wimax_dev->rfkill_input = NULL;
404 error_input_register:
405 if (wimax_dev->rfkill_input)
406 input_free_device(wimax_dev->rfkill_input);
407 error_input_allocate:
408 rfkill_free(wimax_dev->rfkill);
409 error_rfkill_allocate:
410 d_fnend(3, dev, "(wimax_dev %p) = %d\n", wimax_dev, result);
416 * Deregister a WiMAX device's RF Kill support
418 * Ick, we can't call rfkill_free() after rfkill_unregister()...oh
421 * WARNING: wimax_dev->mutex must be unlocked
423 void wimax_rfkill_rm(struct wimax_dev *wimax_dev)
425 struct device *dev = wimax_dev_to_dev(wimax_dev);
426 d_fnstart(3, dev, "(wimax_dev %p)\n", wimax_dev);
427 rfkill_unregister(wimax_dev->rfkill); /* frees */
428 input_unregister_device(wimax_dev->rfkill_input);
429 d_fnend(3, dev, "(wimax_dev %p)\n", wimax_dev);
433 #else /* #ifdef CONFIG_RFKILL */
435 void wimax_report_rfkill_hw(struct wimax_dev *wimax_dev,
436 enum wimax_rf_state state)
439 EXPORT_SYMBOL_GPL(wimax_report_rfkill_hw);
441 void wimax_report_rfkill_sw(struct wimax_dev *wimax_dev,
442 enum wimax_rf_state state)
445 EXPORT_SYMBOL_GPL(wimax_report_rfkill_sw);
447 int wimax_rfkill(struct wimax_dev *wimax_dev,
448 enum wimax_rf_state state)
450 return WIMAX_RF_ON << 1 | WIMAX_RF_ON;
452 EXPORT_SYMBOL_GPL(wimax_rfkill);
454 int wimax_rfkill_add(struct wimax_dev *wimax_dev)
459 void wimax_rfkill_rm(struct wimax_dev *wimax_dev)
463 #endif /* #ifdef CONFIG_RFKILL */
467 * Exporting to user space over generic netlink
469 * Parse the rfkill command from user space, return a combination
470 * value that describe the states of the different toggles.
472 * Only one attribute: the new state requested (on, off or no change,
477 struct nla_policy wimax_gnl_rfkill_policy[WIMAX_GNL_ATTR_MAX + 1] = {
478 [WIMAX_GNL_RFKILL_IFIDX] = {
481 [WIMAX_GNL_RFKILL_STATE] = {
482 .type = NLA_U32 /* enum wimax_rf_state */
488 int wimax_gnl_doit_rfkill(struct sk_buff *skb, struct genl_info *info)
491 struct wimax_dev *wimax_dev;
493 enum wimax_rf_state new_state;
495 d_fnstart(3, NULL, "(skb %p info %p)\n", skb, info);
497 if (info->attrs[WIMAX_GNL_RFKILL_IFIDX] == NULL) {
498 printk(KERN_ERR "WIMAX_GNL_OP_RFKILL: can't find IFIDX "
500 goto error_no_wimax_dev;
502 ifindex = nla_get_u32(info->attrs[WIMAX_GNL_RFKILL_IFIDX]);
503 wimax_dev = wimax_dev_get_by_genl_info(info, ifindex);
504 if (wimax_dev == NULL)
505 goto error_no_wimax_dev;
506 dev = wimax_dev_to_dev(wimax_dev);
508 if (info->attrs[WIMAX_GNL_RFKILL_STATE] == NULL) {
509 dev_err(dev, "WIMAX_GNL_RFKILL: can't find RFKILL_STATE "
513 new_state = nla_get_u32(info->attrs[WIMAX_GNL_RFKILL_STATE]);
515 /* Execute the operation and send the result back to user space */
516 result = wimax_rfkill(wimax_dev, new_state);
518 dev_put(wimax_dev->net_dev);
520 d_fnend(3, NULL, "(skb %p info %p) = %d\n", skb, info, result);
525 struct genl_ops wimax_gnl_rfkill = {
526 .cmd = WIMAX_GNL_OP_RFKILL,
527 .flags = GENL_ADMIN_PERM,
528 .policy = wimax_gnl_rfkill_policy,
529 .doit = wimax_gnl_doit_rfkill,