linux/drivers/input/input-polldev.c
<<
>>
Prefs
   1/*
   2 * Generic implementation of a polled input device
   3
   4 * Copyright (c) 2007 Dmitry Torokhov
   5 *
   6 * This program is free software; you can redistribute it and/or modify it
   7 * under the terms of the GNU General Public License version 2 as published by
   8 * the Free Software Foundation.
   9 */
  10
  11#include <linux/jiffies.h>
  12#include <linux/mutex.h>
  13#include <linux/input-polldev.h>
  14
  15MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
  16MODULE_DESCRIPTION("Generic implementation of a polled input device");
  17MODULE_LICENSE("GPL v2");
  18MODULE_VERSION("0.1");
  19
  20static DEFINE_MUTEX(polldev_mutex);
  21static int polldev_users;
  22static struct workqueue_struct *polldev_wq;
  23
  24static int input_polldev_start_workqueue(void)
  25{
  26        int retval;
  27
  28        retval = mutex_lock_interruptible(&polldev_mutex);
  29        if (retval)
  30                return retval;
  31
  32        if (!polldev_users) {
  33                polldev_wq = create_singlethread_workqueue("ipolldevd");
  34                if (!polldev_wq) {
  35                        printk(KERN_ERR "input-polldev: failed to create "
  36                                "ipolldevd workqueue\n");
  37                        retval = -ENOMEM;
  38                        goto out;
  39                }
  40        }
  41
  42        polldev_users++;
  43
  44 out:
  45        mutex_unlock(&polldev_mutex);
  46        return retval;
  47}
  48
  49static void input_polldev_stop_workqueue(void)
  50{
  51        mutex_lock(&polldev_mutex);
  52
  53        if (!--polldev_users)
  54                destroy_workqueue(polldev_wq);
  55
  56        mutex_unlock(&polldev_mutex);
  57}
  58
  59static void input_polled_device_work(struct work_struct *work)
  60{
  61        struct input_polled_dev *dev =
  62                container_of(work, struct input_polled_dev, work.work);
  63        unsigned long delay;
  64
  65        dev->poll(dev);
  66
  67        delay = msecs_to_jiffies(dev->poll_interval);
  68        if (delay >= HZ)
  69                delay = round_jiffies_relative(delay);
  70
  71        queue_delayed_work(polldev_wq, &dev->work, delay);
  72}
  73
  74static int input_open_polled_device(struct input_dev *input)
  75{
  76        struct input_polled_dev *dev = input_get_drvdata(input);
  77        int error;
  78
  79        error = input_polldev_start_workqueue();
  80        if (error)
  81                return error;
  82
  83        if (dev->flush)
  84                dev->flush(dev);
  85
  86        queue_delayed_work(polldev_wq, &dev->work,
  87                           msecs_to_jiffies(dev->poll_interval));
  88
  89        return 0;
  90}
  91
  92static void input_close_polled_device(struct input_dev *input)
  93{
  94        struct input_polled_dev *dev = input_get_drvdata(input);
  95
  96        cancel_delayed_work_sync(&dev->work);
  97        input_polldev_stop_workqueue();
  98}
  99
 100/**
 101 * input_allocate_polled_device - allocated memory polled device
 102 *
 103 * The function allocates memory for a polled device and also
 104 * for an input device associated with this polled device.
 105 */
 106struct input_polled_dev *input_allocate_polled_device(void)
 107{
 108        struct input_polled_dev *dev;
 109
 110        dev = kzalloc(sizeof(struct input_polled_dev), GFP_KERNEL);
 111        if (!dev)
 112                return NULL;
 113
 114        dev->input = input_allocate_device();
 115        if (!dev->input) {
 116                kfree(dev);
 117                return NULL;
 118        }
 119
 120        return dev;
 121}
 122EXPORT_SYMBOL(input_allocate_polled_device);
 123
 124/**
 125 * input_free_polled_device - free memory allocated for polled device
 126 * @dev: device to free
 127 *
 128 * The function frees memory allocated for polling device and drops
 129 * reference to the associated input device (if present).
 130 */
 131void input_free_polled_device(struct input_polled_dev *dev)
 132{
 133        if (dev) {
 134                input_free_device(dev->input);
 135                kfree(dev);
 136        }
 137}
 138EXPORT_SYMBOL(input_free_polled_device);
 139
 140/**
 141 * input_register_polled_device - register polled device
 142 * @dev: device to register
 143 *
 144 * The function registers previously initialized polled input device
 145 * with input layer. The device should be allocated with call to
 146 * input_allocate_polled_device(). Callers should also set up poll()
 147 * method and set up capabilities (id, name, phys, bits) of the
 148 * corresponing input_dev structure.
 149 */
 150int input_register_polled_device(struct input_polled_dev *dev)
 151{
 152        struct input_dev *input = dev->input;
 153
 154        input_set_drvdata(input, dev);
 155        INIT_DELAYED_WORK(&dev->work, input_polled_device_work);
 156        if (!dev->poll_interval)
 157                dev->poll_interval = 500;
 158        input->open = input_open_polled_device;
 159        input->close = input_close_polled_device;
 160
 161        return input_register_device(input);
 162}
 163EXPORT_SYMBOL(input_register_polled_device);
 164
 165/**
 166 * input_unregister_polled_device - unregister polled device
 167 * @dev: device to unregister
 168 *
 169 * The function unregisters previously registered polled input
 170 * device from input layer. Polling is stopped and device is
 171 * ready to be freed with call to input_free_polled_device().
 172 * Callers should not attempt to access dev->input pointer
 173 * after calling this function.
 174 */
 175void input_unregister_polled_device(struct input_polled_dev *dev)
 176{
 177        input_unregister_device(dev->input);
 178        dev->input = NULL;
 179}
 180EXPORT_SYMBOL(input_unregister_polled_device);
 181
 182