linux/net/rfkill/rfkill-input.c
<<
>>
Prefs
   1/*
   2 * Input layer to RF Kill interface connector
   3 *
   4 * Copyright (c) 2007 Dmitry Torokhov
   5 */
   6
   7/*
   8 * This program is free software; you can redistribute it and/or modify it
   9 * under the terms of the GNU General Public License version 2 as published
  10 * by the Free Software Foundation.
  11 */
  12
  13#include <linux/module.h>
  14#include <linux/input.h>
  15#include <linux/slab.h>
  16#include <linux/workqueue.h>
  17#include <linux/init.h>
  18#include <linux/rfkill.h>
  19#include <linux/sched.h>
  20
  21#include "rfkill-input.h"
  22
  23MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
  24MODULE_DESCRIPTION("Input layer to RF switch connector");
  25MODULE_LICENSE("GPL");
  26
  27enum rfkill_input_master_mode {
  28        RFKILL_INPUT_MASTER_DONOTHING = 0,
  29        RFKILL_INPUT_MASTER_RESTORE = 1,
  30        RFKILL_INPUT_MASTER_UNBLOCKALL = 2,
  31        RFKILL_INPUT_MASTER_MAX,        /* marker */
  32};
  33
  34/* Delay (in ms) between consecutive switch ops */
  35#define RFKILL_OPS_DELAY 200
  36
  37static enum rfkill_input_master_mode rfkill_master_switch_mode =
  38                                        RFKILL_INPUT_MASTER_UNBLOCKALL;
  39module_param_named(master_switch_mode, rfkill_master_switch_mode, uint, 0);
  40MODULE_PARM_DESC(master_switch_mode,
  41        "SW_RFKILL_ALL ON should: 0=do nothing; 1=restore; 2=unblock all");
  42
  43enum rfkill_global_sched_op {
  44        RFKILL_GLOBAL_OP_EPO = 0,
  45        RFKILL_GLOBAL_OP_RESTORE,
  46        RFKILL_GLOBAL_OP_UNLOCK,
  47        RFKILL_GLOBAL_OP_UNBLOCK,
  48};
  49
  50/*
  51 * Currently, the code marked with RFKILL_NEED_SWSET is inactive.
  52 * If handling of EV_SW SW_WLAN/WWAN/BLUETOOTH/etc is needed in the
  53 * future, when such events are added, that code will be necessary.
  54 */
  55
  56struct rfkill_task {
  57        struct delayed_work dwork;
  58
  59        /* ensures that task is serialized */
  60        struct mutex mutex;
  61
  62        /* protects everything below */
  63        spinlock_t lock;
  64
  65        /* pending regular switch operations (1=pending) */
  66        unsigned long sw_pending[BITS_TO_LONGS(RFKILL_TYPE_MAX)];
  67
  68#ifdef RFKILL_NEED_SWSET
  69        /* set operation pending (1=pending) */
  70        unsigned long sw_setpending[BITS_TO_LONGS(RFKILL_TYPE_MAX)];
  71
  72        /* desired state for pending set operation (1=unblock) */
  73        unsigned long sw_newstate[BITS_TO_LONGS(RFKILL_TYPE_MAX)];
  74#endif
  75
  76        /* should the state be complemented (1=yes) */
  77        unsigned long sw_togglestate[BITS_TO_LONGS(RFKILL_TYPE_MAX)];
  78
  79        bool global_op_pending;
  80        enum rfkill_global_sched_op op;
  81
  82        /* last time it was scheduled */
  83        unsigned long last_scheduled;
  84};
  85
  86static void __rfkill_handle_global_op(enum rfkill_global_sched_op op)
  87{
  88        unsigned int i;
  89
  90        switch (op) {
  91        case RFKILL_GLOBAL_OP_EPO:
  92                rfkill_epo();
  93                break;
  94        case RFKILL_GLOBAL_OP_RESTORE:
  95                rfkill_restore_states();
  96                break;
  97        case RFKILL_GLOBAL_OP_UNLOCK:
  98                rfkill_remove_epo_lock();
  99                break;
 100        case RFKILL_GLOBAL_OP_UNBLOCK:
 101                rfkill_remove_epo_lock();
 102                for (i = 0; i < RFKILL_TYPE_MAX; i++)
 103                        rfkill_switch_all(i, RFKILL_STATE_UNBLOCKED);
 104                break;
 105        default:
 106                /* memory corruption or bug, fail safely */
 107                rfkill_epo();
 108                WARN(1, "Unknown requested operation %d! "
 109                        "rfkill Emergency Power Off activated\n",
 110                        op);
 111        }
 112}
 113
 114#ifdef RFKILL_NEED_SWSET
 115static void __rfkill_handle_normal_op(const enum rfkill_type type,
 116                        const bool sp, const bool s, const bool c)
 117{
 118        enum rfkill_state state;
 119
 120        if (sp)
 121                state = (s) ? RFKILL_STATE_UNBLOCKED :
 122                              RFKILL_STATE_SOFT_BLOCKED;
 123        else
 124                state = rfkill_get_global_state(type);
 125
 126        if (c)
 127                state = rfkill_state_complement(state);
 128
 129        rfkill_switch_all(type, state);
 130}
 131#else
 132static void __rfkill_handle_normal_op(const enum rfkill_type type,
 133                        const bool c)
 134{
 135        enum rfkill_state state;
 136
 137        state = rfkill_get_global_state(type);
 138        if (c)
 139                state = rfkill_state_complement(state);
 140
 141        rfkill_switch_all(type, state);
 142}
 143#endif
 144
 145static void rfkill_task_handler(struct work_struct *work)
 146{
 147        struct rfkill_task *task = container_of(work,
 148                                        struct rfkill_task, dwork.work);
 149        bool doit = true;
 150
 151        mutex_lock(&task->mutex);
 152
 153        spin_lock_irq(&task->lock);
 154        while (doit) {
 155                if (task->global_op_pending) {
 156                        enum rfkill_global_sched_op op = task->op;
 157                        task->global_op_pending = false;
 158                        memset(task->sw_pending, 0, sizeof(task->sw_pending));
 159                        spin_unlock_irq(&task->lock);
 160
 161                        __rfkill_handle_global_op(op);
 162
 163                        /* make sure we do at least one pass with
 164                         * !task->global_op_pending */
 165                        spin_lock_irq(&task->lock);
 166                        continue;
 167                } else if (!rfkill_is_epo_lock_active()) {
 168                        unsigned int i = 0;
 169
 170                        while (!task->global_op_pending &&
 171                                                i < RFKILL_TYPE_MAX) {
 172                                if (test_and_clear_bit(i, task->sw_pending)) {
 173                                        bool c;
 174#ifdef RFKILL_NEED_SWSET
 175                                        bool sp, s;
 176                                        sp = test_and_clear_bit(i,
 177                                                        task->sw_setpending);
 178                                        s = test_bit(i, task->sw_newstate);
 179#endif
 180                                        c = test_and_clear_bit(i,
 181                                                        task->sw_togglestate);
 182                                        spin_unlock_irq(&task->lock);
 183
 184#ifdef RFKILL_NEED_SWSET
 185                                        __rfkill_handle_normal_op(i, sp, s, c);
 186#else
 187                                        __rfkill_handle_normal_op(i, c);
 188#endif
 189
 190                                        spin_lock_irq(&task->lock);
 191                                }
 192                                i++;
 193                        }
 194                }
 195                doit = task->global_op_pending;
 196        }
 197        spin_unlock_irq(&task->lock);
 198
 199        mutex_unlock(&task->mutex);
 200}
 201
 202static struct rfkill_task rfkill_task = {
 203        .dwork = __DELAYED_WORK_INITIALIZER(rfkill_task.dwork,
 204                                rfkill_task_handler),
 205        .mutex = __MUTEX_INITIALIZER(rfkill_task.mutex),
 206        .lock = __SPIN_LOCK_UNLOCKED(rfkill_task.lock),
 207};
 208
 209static unsigned long rfkill_ratelimit(const unsigned long last)
 210{
 211        const unsigned long delay = msecs_to_jiffies(RFKILL_OPS_DELAY);
 212        return (time_after(jiffies, last + delay)) ? 0 : delay;
 213}
 214
 215static void rfkill_schedule_ratelimited(void)
 216{
 217        if (!delayed_work_pending(&rfkill_task.dwork)) {
 218                schedule_delayed_work(&rfkill_task.dwork,
 219                                rfkill_ratelimit(rfkill_task.last_scheduled));
 220                rfkill_task.last_scheduled = jiffies;
 221        }
 222}
 223
 224static void rfkill_schedule_global_op(enum rfkill_global_sched_op op)
 225{
 226        unsigned long flags;
 227
 228        spin_lock_irqsave(&rfkill_task.lock, flags);
 229        rfkill_task.op = op;
 230        rfkill_task.global_op_pending = true;
 231        if (op == RFKILL_GLOBAL_OP_EPO && !rfkill_is_epo_lock_active()) {
 232                /* bypass the limiter for EPO */
 233                cancel_delayed_work(&rfkill_task.dwork);
 234                schedule_delayed_work(&rfkill_task.dwork, 0);
 235                rfkill_task.last_scheduled = jiffies;
 236        } else
 237                rfkill_schedule_ratelimited();
 238        spin_unlock_irqrestore(&rfkill_task.lock, flags);
 239}
 240
 241#ifdef RFKILL_NEED_SWSET
 242/* Use this if you need to add EV_SW SW_WLAN/WWAN/BLUETOOTH/etc handling */
 243
 244static void rfkill_schedule_set(enum rfkill_type type,
 245                                enum rfkill_state desired_state)
 246{
 247        unsigned long flags;
 248
 249        if (rfkill_is_epo_lock_active())
 250                return;
 251
 252        spin_lock_irqsave(&rfkill_task.lock, flags);
 253        if (!rfkill_task.global_op_pending) {
 254                set_bit(type, rfkill_task.sw_pending);
 255                set_bit(type, rfkill_task.sw_setpending);
 256                clear_bit(type, rfkill_task.sw_togglestate);
 257                if (desired_state)
 258                        set_bit(type,  rfkill_task.sw_newstate);
 259                else
 260                        clear_bit(type, rfkill_task.sw_newstate);
 261                rfkill_schedule_ratelimited();
 262        }
 263        spin_unlock_irqrestore(&rfkill_task.lock, flags);
 264}
 265#endif
 266
 267static void rfkill_schedule_toggle(enum rfkill_type type)
 268{
 269        unsigned long flags;
 270
 271        if (rfkill_is_epo_lock_active())
 272                return;
 273
 274        spin_lock_irqsave(&rfkill_task.lock, flags);
 275        if (!rfkill_task.global_op_pending) {
 276                set_bit(type, rfkill_task.sw_pending);
 277                change_bit(type, rfkill_task.sw_togglestate);
 278                rfkill_schedule_ratelimited();
 279        }
 280        spin_unlock_irqrestore(&rfkill_task.lock, flags);
 281}
 282
 283static void rfkill_schedule_evsw_rfkillall(int state)
 284{
 285        if (state) {
 286                switch (rfkill_master_switch_mode) {
 287                case RFKILL_INPUT_MASTER_UNBLOCKALL:
 288                        rfkill_schedule_global_op(RFKILL_GLOBAL_OP_UNBLOCK);
 289                        break;
 290                case RFKILL_INPUT_MASTER_RESTORE:
 291                        rfkill_schedule_global_op(RFKILL_GLOBAL_OP_RESTORE);
 292                        break;
 293                case RFKILL_INPUT_MASTER_DONOTHING:
 294                        rfkill_schedule_global_op(RFKILL_GLOBAL_OP_UNLOCK);
 295                        break;
 296                default:
 297                        /* memory corruption or driver bug! fail safely */
 298                        rfkill_schedule_global_op(RFKILL_GLOBAL_OP_EPO);
 299                        WARN(1, "Unknown rfkill_master_switch_mode (%d), "
 300                                "driver bug or memory corruption detected!\n",
 301                                rfkill_master_switch_mode);
 302                        break;
 303                }
 304        } else
 305                rfkill_schedule_global_op(RFKILL_GLOBAL_OP_EPO);
 306}
 307
 308static void rfkill_event(struct input_handle *handle, unsigned int type,
 309                        unsigned int code, int data)
 310{
 311        if (type == EV_KEY && data == 1) {
 312                enum rfkill_type t;
 313
 314                switch (code) {
 315                case KEY_WLAN:
 316                        t = RFKILL_TYPE_WLAN;
 317                        break;
 318                case KEY_BLUETOOTH:
 319                        t = RFKILL_TYPE_BLUETOOTH;
 320                        break;
 321                case KEY_UWB:
 322                        t = RFKILL_TYPE_UWB;
 323                        break;
 324                case KEY_WIMAX:
 325                        t = RFKILL_TYPE_WIMAX;
 326                        break;
 327                default:
 328                        return;
 329                }
 330                rfkill_schedule_toggle(t);
 331                return;
 332        } else if (type == EV_SW) {
 333                switch (code) {
 334                case SW_RFKILL_ALL:
 335                        rfkill_schedule_evsw_rfkillall(data);
 336                        return;
 337                default:
 338                        return;
 339                }
 340        }
 341}
 342
 343static int rfkill_connect(struct input_handler *handler, struct input_dev *dev,
 344                          const struct input_device_id *id)
 345{
 346        struct input_handle *handle;
 347        int error;
 348
 349        handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
 350        if (!handle)
 351                return -ENOMEM;
 352
 353        handle->dev = dev;
 354        handle->handler = handler;
 355        handle->name = "rfkill";
 356
 357        /* causes rfkill_start() to be called */
 358        error = input_register_handle(handle);
 359        if (error)
 360                goto err_free_handle;
 361
 362        error = input_open_device(handle);
 363        if (error)
 364                goto err_unregister_handle;
 365
 366        return 0;
 367
 368 err_unregister_handle:
 369        input_unregister_handle(handle);
 370 err_free_handle:
 371        kfree(handle);
 372        return error;
 373}
 374
 375static void rfkill_start(struct input_handle *handle)
 376{
 377        /* Take event_lock to guard against configuration changes, we
 378         * should be able to deal with concurrency with rfkill_event()
 379         * just fine (which event_lock will also avoid). */
 380        spin_lock_irq(&handle->dev->event_lock);
 381
 382        if (test_bit(EV_SW, handle->dev->evbit)) {
 383                if (test_bit(SW_RFKILL_ALL, handle->dev->swbit))
 384                        rfkill_schedule_evsw_rfkillall(test_bit(SW_RFKILL_ALL,
 385                                                        handle->dev->sw));
 386                /* add resync for further EV_SW events here */
 387        }
 388
 389        spin_unlock_irq(&handle->dev->event_lock);
 390}
 391
 392static void rfkill_disconnect(struct input_handle *handle)
 393{
 394        input_close_device(handle);
 395        input_unregister_handle(handle);
 396        kfree(handle);
 397}
 398
 399static const struct input_device_id rfkill_ids[] = {
 400        {
 401                .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT,
 402                .evbit = { BIT_MASK(EV_KEY) },
 403                .keybit = { [BIT_WORD(KEY_WLAN)] = BIT_MASK(KEY_WLAN) },
 404        },
 405        {
 406                .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT,
 407                .evbit = { BIT_MASK(EV_KEY) },
 408                .keybit = { [BIT_WORD(KEY_BLUETOOTH)] = BIT_MASK(KEY_BLUETOOTH) },
 409        },
 410        {
 411                .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT,
 412                .evbit = { BIT_MASK(EV_KEY) },
 413                .keybit = { [BIT_WORD(KEY_UWB)] = BIT_MASK(KEY_UWB) },
 414        },
 415        {
 416                .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT,
 417                .evbit = { BIT_MASK(EV_KEY) },
 418                .keybit = { [BIT_WORD(KEY_WIMAX)] = BIT_MASK(KEY_WIMAX) },
 419        },
 420        {
 421                .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_SWBIT,
 422                .evbit = { BIT(EV_SW) },
 423                .swbit = { [BIT_WORD(SW_RFKILL_ALL)] = BIT_MASK(SW_RFKILL_ALL) },
 424        },
 425        { }
 426};
 427
 428static struct input_handler rfkill_handler = {
 429        .event =        rfkill_event,
 430        .connect =      rfkill_connect,
 431        .disconnect =   rfkill_disconnect,
 432        .start =        rfkill_start,
 433        .name =         "rfkill",
 434        .id_table =     rfkill_ids,
 435};
 436
 437static int __init rfkill_handler_init(void)
 438{
 439        if (rfkill_master_switch_mode >= RFKILL_INPUT_MASTER_MAX)
 440                return -EINVAL;
 441
 442        /*
 443         * The penalty to not doing this is a possible RFKILL_OPS_DELAY delay
 444         * at the first use.  Acceptable, but if we can avoid it, why not?
 445         */
 446        rfkill_task.last_scheduled =
 447                        jiffies - msecs_to_jiffies(RFKILL_OPS_DELAY) - 1;
 448        return input_register_handler(&rfkill_handler);
 449}
 450
 451static void __exit rfkill_handler_exit(void)
 452{
 453        input_unregister_handler(&rfkill_handler);
 454        cancel_delayed_work_sync(&rfkill_task.dwork);
 455        rfkill_remove_epo_lock();
 456}
 457
 458module_init(rfkill_handler_init);
 459module_exit(rfkill_handler_exit);
 460
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.