linux/drivers/staging/android/timed_output.c
<<
>>
Prefs
   1/* drivers/misc/timed_output.c
   2 *
   3 * Copyright (C) 2009 Google, Inc.
   4 * Author: Mike Lockwood <lockwood@android.com>
   5 *
   6 * This software is licensed under the terms of the GNU General Public
   7 * License version 2, as published by the Free Software Foundation, and
   8 * may be copied, distributed, and modified under those terms.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 */
  16
  17#define pr_fmt(fmt) "timed_output: " fmt
  18
  19#include <linux/module.h>
  20#include <linux/types.h>
  21#include <linux/device.h>
  22#include <linux/fs.h>
  23#include <linux/err.h>
  24
  25#include "timed_output.h"
  26
  27static struct class *timed_output_class;
  28static atomic_t device_count;
  29
  30static ssize_t enable_show(struct device *dev, struct device_attribute *attr,
  31                char *buf)
  32{
  33        struct timed_output_dev *tdev = dev_get_drvdata(dev);
  34        int remaining = tdev->get_time(tdev);
  35
  36        return sprintf(buf, "%d\n", remaining);
  37}
  38
  39static ssize_t enable_store(
  40                struct device *dev, struct device_attribute *attr,
  41                const char *buf, size_t size)
  42{
  43        struct timed_output_dev *tdev = dev_get_drvdata(dev);
  44        int value;
  45
  46        if (sscanf(buf, "%d", &value) != 1)
  47                return -EINVAL;
  48
  49        tdev->enable(tdev, value);
  50
  51        return size;
  52}
  53
  54static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, enable_show, enable_store);
  55
  56static int create_timed_output_class(void)
  57{
  58        if (!timed_output_class) {
  59                timed_output_class = class_create(THIS_MODULE, "timed_output");
  60                if (IS_ERR(timed_output_class))
  61                        return PTR_ERR(timed_output_class);
  62                atomic_set(&device_count, 0);
  63        }
  64
  65        return 0;
  66}
  67
  68int timed_output_dev_register(struct timed_output_dev *tdev)
  69{
  70        int ret;
  71
  72        if (!tdev || !tdev->name || !tdev->enable || !tdev->get_time)
  73                return -EINVAL;
  74
  75        ret = create_timed_output_class();
  76        if (ret < 0)
  77                return ret;
  78
  79        tdev->index = atomic_inc_return(&device_count);
  80        tdev->dev = device_create(timed_output_class, NULL,
  81                MKDEV(0, tdev->index), NULL, tdev->name);
  82        if (IS_ERR(tdev->dev))
  83                return PTR_ERR(tdev->dev);
  84
  85        ret = device_create_file(tdev->dev, &dev_attr_enable);
  86        if (ret < 0)
  87                goto err_create_file;
  88
  89        dev_set_drvdata(tdev->dev, tdev);
  90        tdev->state = 0;
  91        return 0;
  92
  93err_create_file:
  94        device_destroy(timed_output_class, MKDEV(0, tdev->index));
  95        pr_err("failed to register driver %s\n",
  96                        tdev->name);
  97
  98        return ret;
  99}
 100EXPORT_SYMBOL_GPL(timed_output_dev_register);
 101
 102void timed_output_dev_unregister(struct timed_output_dev *tdev)
 103{
 104        tdev->enable(tdev, 0);
 105        device_remove_file(tdev->dev, &dev_attr_enable);
 106        device_destroy(timed_output_class, MKDEV(0, tdev->index));
 107        dev_set_drvdata(tdev->dev, NULL);
 108}
 109EXPORT_SYMBOL_GPL(timed_output_dev_unregister);
 110
 111static int __init timed_output_init(void)
 112{
 113        return create_timed_output_class();
 114}
 115
 116static void __exit timed_output_exit(void)
 117{
 118        class_destroy(timed_output_class);
 119}
 120
 121module_init(timed_output_init);
 122module_exit(timed_output_exit);
 123
 124MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
 125MODULE_DESCRIPTION("timed output class driver");
 126MODULE_LICENSE("GPL");
 127