blob: b41429f379fef46555fa4cf7426cbc5190b5f93a [file] [log] [blame]
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +09001/* 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
Sachin Kamatc810a392012-06-05 16:40:10 +053017#define pr_fmt(fmt) "timed_output: " fmt
18
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +090019#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,
Greg Kroah-Hartman9d3ab802013-08-24 10:27:29 -070031 char *buf)
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +090032{
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
Greg Kroah-Hartman9d3ab802013-08-24 10:27:29 -070039static ssize_t enable_store(struct device *dev, struct device_attribute *attr,
40 const char *buf, size_t size)
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +090041{
42 struct timed_output_dev *tdev = dev_get_drvdata(dev);
43 int value;
Murilo Opsfelder Araujo6aa26212014-07-28 20:45:06 -030044 int rc;
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +090045
Murilo Opsfelder Araujo6aa26212014-07-28 20:45:06 -030046 rc = kstrtoint(buf, 0, &value);
47 if (rc != 0)
Mike Lockwood8bfe15f2010-04-17 12:01:35 -040048 return -EINVAL;
49
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +090050 tdev->enable(tdev, value);
51
52 return size;
53}
Greg Kroah-Hartman9d3ab802013-08-24 10:27:29 -070054static DEVICE_ATTR_RW(enable);
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +090055
Greg Kroah-Hartman9d3ab802013-08-24 10:27:29 -070056static struct attribute *timed_output_attrs[] = {
57 &dev_attr_enable.attr,
58 NULL,
59};
60ATTRIBUTE_GROUPS(timed_output);
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +090061
62static int create_timed_output_class(void)
63{
64 if (!timed_output_class) {
65 timed_output_class = class_create(THIS_MODULE, "timed_output");
66 if (IS_ERR(timed_output_class))
67 return PTR_ERR(timed_output_class);
68 atomic_set(&device_count, 0);
Greg Kroah-Hartman9d3ab802013-08-24 10:27:29 -070069 timed_output_class->dev_groups = timed_output_groups;
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +090070 }
71
72 return 0;
73}
74
75int timed_output_dev_register(struct timed_output_dev *tdev)
76{
77 int ret;
78
79 if (!tdev || !tdev->name || !tdev->enable || !tdev->get_time)
80 return -EINVAL;
81
82 ret = create_timed_output_class();
83 if (ret < 0)
84 return ret;
85
86 tdev->index = atomic_inc_return(&device_count);
87 tdev->dev = device_create(timed_output_class, NULL,
Kees Cook02aa2a32013-07-03 15:04:56 -070088 MKDEV(0, tdev->index), NULL, "%s", tdev->name);
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +090089 if (IS_ERR(tdev->dev))
90 return PTR_ERR(tdev->dev);
91
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +090092 dev_set_drvdata(tdev->dev, tdev);
93 tdev->state = 0;
94 return 0;
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +090095}
96EXPORT_SYMBOL_GPL(timed_output_dev_register);
97
98void timed_output_dev_unregister(struct timed_output_dev *tdev)
99{
Kim, Milod9a861d2012-04-26 22:01:10 -0700100 tdev->enable(tdev, 0);
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +0900101 device_destroy(timed_output_class, MKDEV(0, tdev->index));
Greg Kroah-Hartman355b0502011-11-30 20:18:14 +0900102}
103EXPORT_SYMBOL_GPL(timed_output_dev_unregister);
104
105static int __init timed_output_init(void)
106{
107 return create_timed_output_class();
108}
109
110static void __exit timed_output_exit(void)
111{
112 class_destroy(timed_output_class);
113}
114
115module_init(timed_output_init);
116module_exit(timed_output_exit);
117
118MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
119MODULE_DESCRIPTION("timed output class driver");
120MODULE_LICENSE("GPL");