Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / staging / android / timed_output.c
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
27 static struct class *timed_output_class;
28 static atomic_t device_count;
29
30 static 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
39 static ssize_t enable_store(struct device *dev, struct device_attribute *attr,
40                             const char *buf, size_t size)
41 {
42         struct timed_output_dev *tdev = dev_get_drvdata(dev);
43         int value;
44         int rc;
45
46         rc = kstrtoint(buf, 0, &value);
47         if (rc != 0)
48                 return -EINVAL;
49
50         tdev->enable(tdev, value);
51
52         return size;
53 }
54 static DEVICE_ATTR_RW(enable);
55
56 static struct attribute *timed_output_attrs[] = {
57         &dev_attr_enable.attr,
58         NULL,
59 };
60 ATTRIBUTE_GROUPS(timed_output);
61
62 static 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);
69                 timed_output_class->dev_groups = timed_output_groups;
70         }
71
72         return 0;
73 }
74
75 int 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,
88                 MKDEV(0, tdev->index), NULL, "%s", tdev->name);
89         if (IS_ERR(tdev->dev))
90                 return PTR_ERR(tdev->dev);
91
92         dev_set_drvdata(tdev->dev, tdev);
93         tdev->state = 0;
94         return 0;
95 }
96 EXPORT_SYMBOL_GPL(timed_output_dev_register);
97
98 void timed_output_dev_unregister(struct timed_output_dev *tdev)
99 {
100         tdev->enable(tdev, 0);
101         device_destroy(timed_output_class, MKDEV(0, tdev->index));
102 }
103 EXPORT_SYMBOL_GPL(timed_output_dev_unregister);
104
105 static int __init timed_output_init(void)
106 {
107         return create_timed_output_class();
108 }
109
110 static void __exit timed_output_exit(void)
111 {
112         class_destroy(timed_output_class);
113 }
114
115 module_init(timed_output_init);
116 module_exit(timed_output_exit);
117
118 MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
119 MODULE_DESCRIPTION("timed output class driver");
120 MODULE_LICENSE("GPL");