2011-11-30 04:18:14 -07:00
|
|
|
/* drivers/misc/timed_output.c
|
|
|
|
*
|
|
|
|
* Copyright (C) 2009 Google, Inc.
|
|
|
|
* Author: Mike Lockwood <lockwood@android.com>
|
|
|
|
*
|
|
|
|
* This software is licensed under the terms of the GNU General Public
|
|
|
|
* License version 2, as published by the Free Software Foundation, and
|
|
|
|
* may be copied, distributed, and modified under those terms.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2012-06-05 05:10:10 -06:00
|
|
|
#define pr_fmt(fmt) "timed_output: " fmt
|
|
|
|
|
2011-11-30 04:18:14 -07:00
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/types.h>
|
|
|
|
#include <linux/device.h>
|
|
|
|
#include <linux/fs.h>
|
|
|
|
#include <linux/err.h>
|
|
|
|
|
|
|
|
#include "timed_output.h"
|
|
|
|
|
|
|
|
static struct class *timed_output_class;
|
|
|
|
static atomic_t device_count;
|
|
|
|
|
|
|
|
static ssize_t enable_show(struct device *dev, struct device_attribute *attr,
|
2013-08-24 11:27:29 -06:00
|
|
|
char *buf)
|
2011-11-30 04:18:14 -07:00
|
|
|
{
|
|
|
|
struct timed_output_dev *tdev = dev_get_drvdata(dev);
|
|
|
|
int remaining = tdev->get_time(tdev);
|
|
|
|
|
|
|
|
return sprintf(buf, "%d\n", remaining);
|
|
|
|
}
|
|
|
|
|
2013-08-24 11:27:29 -06:00
|
|
|
static ssize_t enable_store(struct device *dev, struct device_attribute *attr,
|
|
|
|
const char *buf, size_t size)
|
2011-11-30 04:18:14 -07:00
|
|
|
{
|
|
|
|
struct timed_output_dev *tdev = dev_get_drvdata(dev);
|
|
|
|
int value;
|
|
|
|
|
2010-04-17 10:01:35 -06:00
|
|
|
if (sscanf(buf, "%d", &value) != 1)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2011-11-30 04:18:14 -07:00
|
|
|
tdev->enable(tdev, value);
|
|
|
|
|
|
|
|
return size;
|
|
|
|
}
|
2013-08-24 11:27:29 -06:00
|
|
|
static DEVICE_ATTR_RW(enable);
|
2011-11-30 04:18:14 -07:00
|
|
|
|
2013-08-24 11:27:29 -06:00
|
|
|
static struct attribute *timed_output_attrs[] = {
|
|
|
|
&dev_attr_enable.attr,
|
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
ATTRIBUTE_GROUPS(timed_output);
|
2011-11-30 04:18:14 -07:00
|
|
|
|
|
|
|
static int create_timed_output_class(void)
|
|
|
|
{
|
|
|
|
if (!timed_output_class) {
|
|
|
|
timed_output_class = class_create(THIS_MODULE, "timed_output");
|
|
|
|
if (IS_ERR(timed_output_class))
|
|
|
|
return PTR_ERR(timed_output_class);
|
|
|
|
atomic_set(&device_count, 0);
|
2013-08-24 11:27:29 -06:00
|
|
|
timed_output_class->dev_groups = timed_output_groups;
|
2011-11-30 04:18:14 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int timed_output_dev_register(struct timed_output_dev *tdev)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (!tdev || !tdev->name || !tdev->enable || !tdev->get_time)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
ret = create_timed_output_class();
|
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
tdev->index = atomic_inc_return(&device_count);
|
|
|
|
tdev->dev = device_create(timed_output_class, NULL,
|
2013-07-03 16:04:56 -06:00
|
|
|
MKDEV(0, tdev->index), NULL, "%s", tdev->name);
|
2011-11-30 04:18:14 -07:00
|
|
|
if (IS_ERR(tdev->dev))
|
|
|
|
return PTR_ERR(tdev->dev);
|
|
|
|
|
|
|
|
dev_set_drvdata(tdev->dev, tdev);
|
|
|
|
tdev->state = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(timed_output_dev_register);
|
|
|
|
|
|
|
|
void timed_output_dev_unregister(struct timed_output_dev *tdev)
|
|
|
|
{
|
2012-04-26 23:01:10 -06:00
|
|
|
tdev->enable(tdev, 0);
|
2011-11-30 04:18:14 -07:00
|
|
|
device_destroy(timed_output_class, MKDEV(0, tdev->index));
|
|
|
|
dev_set_drvdata(tdev->dev, NULL);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(timed_output_dev_unregister);
|
|
|
|
|
|
|
|
static int __init timed_output_init(void)
|
|
|
|
{
|
|
|
|
return create_timed_output_class();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void __exit timed_output_exit(void)
|
|
|
|
{
|
|
|
|
class_destroy(timed_output_class);
|
|
|
|
}
|
|
|
|
|
|
|
|
module_init(timed_output_init);
|
|
|
|
module_exit(timed_output_exit);
|
|
|
|
|
|
|
|
MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
|
|
|
|
MODULE_DESCRIPTION("timed output class driver");
|
|
|
|
MODULE_LICENSE("GPL");
|