blob: bbf168c106235e1aa82fb87d7b568b5fcb9df21b [file] [log] [blame]
Jie Cheng68154022013-11-06 07:59:34 -08001/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/module.h>
14#include <linux/kernel.h>
15#include <linux/init.h>
16#include <linux/list.h>
17#include <linux/spinlock.h>
18#include <linux/device.h>
19#include <linux/err.h>
20#include <linux/ctype.h>
21#include <linux/rwsem.h>
22#include <linux/sensors.h>
23
24static struct class *sensors_class;
25
26DECLARE_RWSEM(sensors_list_lock);
27LIST_HEAD(sensors_list);
28
29static ssize_t sensors_name_show(struct device *dev,
30 struct device_attribute *attr, char *buf)
31{
32 struct sensors_classdev *sensors_cdev = dev_get_drvdata(dev);
33 return snprintf(buf, PAGE_SIZE, "%s\n", sensors_cdev->name);
34}
35
36static ssize_t sensors_vendor_show(struct device *dev,
37 struct device_attribute *attr, char *buf)
38{
39 struct sensors_classdev *sensors_cdev = dev_get_drvdata(dev);
40 return snprintf(buf, PAGE_SIZE, "%s\n", sensors_cdev->vendor);
41}
42
43static ssize_t sensors_version_show(struct device *dev,
44 struct device_attribute *attr, char *buf)
45{
46 struct sensors_classdev *sensors_cdev = dev_get_drvdata(dev);
47 return snprintf(buf, PAGE_SIZE, "%d\n", sensors_cdev->version);
48}
49
50static ssize_t sensors_handle_show(struct device *dev,
51 struct device_attribute *attr, char *buf)
52{
53 struct sensors_classdev *sensors_cdev = dev_get_drvdata(dev);
54 return snprintf(buf, PAGE_SIZE, "%d\n", sensors_cdev->handle);
55}
56
57static ssize_t sensors_type_show(struct device *dev,
58 struct device_attribute *attr, char *buf)
59{
60 struct sensors_classdev *sensors_cdev = dev_get_drvdata(dev);
61 return snprintf(buf, PAGE_SIZE, "%d\n", sensors_cdev->type);
62}
63
64static ssize_t sensors_max_range_show(struct device *dev,
65 struct device_attribute *attr, char *buf)
66{
67 struct sensors_classdev *sensors_cdev = dev_get_drvdata(dev);
68 return snprintf(buf, PAGE_SIZE, "%s\n", sensors_cdev->max_range);
69}
70
71static ssize_t sensors_resolution_show(struct device *dev,
72 struct device_attribute *attr, char *buf)
73{
74 struct sensors_classdev *sensors_cdev = dev_get_drvdata(dev);
75 return snprintf(buf, PAGE_SIZE, "%s\n", sensors_cdev->resolution);
76}
77
78static ssize_t sensors_power_show(struct device *dev,
79 struct device_attribute *attr, char *buf)
80{
81 struct sensors_classdev *sensors_cdev = dev_get_drvdata(dev);
82 return snprintf(buf, PAGE_SIZE, "%s\n", sensors_cdev->sensor_power);
83}
84
85static ssize_t sensors_min_delay_show(struct device *dev,
86 struct device_attribute *attr, char *buf)
87{
88 struct sensors_classdev *sensors_cdev = dev_get_drvdata(dev);
89 return snprintf(buf, PAGE_SIZE, "%d\n", sensors_cdev->min_delay);
90}
91
92static ssize_t sensors_fifo_event_show(struct device *dev,
93 struct device_attribute *attr, char *buf)
94{
95 struct sensors_classdev *sensors_cdev = dev_get_drvdata(dev);
96 return snprintf(buf, PAGE_SIZE, "%d\n",
97 sensors_cdev->fifo_reserved_event_count);
98}
99
100static ssize_t sensors_fifo_max_show(struct device *dev,
101 struct device_attribute *attr, char *buf)
102{
103 struct sensors_classdev *sensors_cdev = dev_get_drvdata(dev);
104 return snprintf(buf, PAGE_SIZE, "%d\n",
105 sensors_cdev->fifo_max_event_count);
106}
107
Jie Cheng82fd7562013-12-18 16:45:28 +0800108static ssize_t sensors_enable_store(struct device *dev,
109 struct device_attribute *attr, const char *buf, size_t size)
110{
111 struct sensors_classdev *sensors_cdev = dev_get_drvdata(dev);
112 ssize_t ret = -EINVAL;
113 unsigned long data = 0;
114
115 ret = kstrtoul(buf, 10, &data);
116 if (ret)
117 return ret;
118 if (data > 1) {
119 dev_err(dev, "Invalid value of input, input=%ld\n", data);
120 return -EINVAL;
121 }
122
123 if (sensors_cdev->sensors_enable == NULL) {
124 dev_err(dev, "Invalid sensor class enable handle\n");
125 return -EINVAL;
126 }
127 ret = sensors_cdev->sensors_enable(sensors_cdev, data);
128 if (ret)
129 return ret;
130
131 sensors_cdev->enabled = data;
132 return size;
133}
134
135
136static ssize_t sensors_enable_show(struct device *dev,
137 struct device_attribute *attr, char *buf)
138{
139 struct sensors_classdev *sensors_cdev = dev_get_drvdata(dev);
140 return snprintf(buf, PAGE_SIZE, "%u\n",
141 sensors_cdev->enabled);
142}
143
144static ssize_t sensors_delay_store(struct device *dev,
145 struct device_attribute *attr, const char *buf, size_t size)
146{
147 struct sensors_classdev *sensors_cdev = dev_get_drvdata(dev);
148 ssize_t ret = -EINVAL;
149 unsigned long data = 0;
150
151 ret = kstrtoul(buf, 10, &data);
152 if (ret)
153 return ret;
154 /* The data unit is millisecond, the min_delay unit is microseconds. */
155 if ((data * 1000) < sensors_cdev->min_delay) {
156 dev_err(dev, "Invalid value of delay, delay=%ld\n", data);
157 return -EINVAL;
158 }
159 if (sensors_cdev->sensors_poll_delay == NULL) {
160 dev_err(dev, "Invalid sensor class delay handle\n");
161 return -EINVAL;
162 }
163 ret = sensors_cdev->sensors_poll_delay(sensors_cdev, data);
164 if (ret)
165 return ret;
166
167 sensors_cdev->delay_msec = data;
168 return size;
169}
170
171static ssize_t sensors_delay_show(struct device *dev,
172 struct device_attribute *attr, char *buf)
173{
174 struct sensors_classdev *sensors_cdev = dev_get_drvdata(dev);
175 return snprintf(buf, PAGE_SIZE, "%u\n",
176 sensors_cdev->delay_msec);
177}
178
179
Jie Cheng68154022013-11-06 07:59:34 -0800180static struct device_attribute sensors_class_attrs[] = {
Jie Chengc37d2d52013-12-04 14:21:03 +0800181 __ATTR(name, 0444, sensors_name_show, NULL),
182 __ATTR(vendor, 0444, sensors_vendor_show, NULL),
183 __ATTR(version, 0444, sensors_version_show, NULL),
184 __ATTR(handle, 0444, sensors_handle_show, NULL),
185 __ATTR(type, 0444, sensors_type_show, NULL),
186 __ATTR(max_range, 0444, sensors_max_range_show, NULL),
187 __ATTR(resolution, 0444, sensors_resolution_show, NULL),
188 __ATTR(sensor_power, 0444, sensors_power_show, NULL),
189 __ATTR(min_delay, 0444, sensors_min_delay_show, NULL),
190 __ATTR(fifo_reserved_event_count, 0444, sensors_fifo_event_show, NULL),
191 __ATTR(fifo_max_event_count, 0444, sensors_fifo_max_show, NULL),
Jie Cheng82fd7562013-12-18 16:45:28 +0800192 __ATTR(enable, 0664, sensors_enable_show, sensors_enable_store),
193 __ATTR(poll_delay, 0664, sensors_delay_show, sensors_delay_store),
Jie Cheng68154022013-11-06 07:59:34 -0800194 __ATTR_NULL,
195};
196
197/**
198 * sensors_classdev_register - register a new object of sensors_classdev class.
199 * @parent: The device to register.
200 * @sensors_cdev: the sensors_classdev structure for this device.
201*/
202int sensors_classdev_register(struct device *parent,
203 struct sensors_classdev *sensors_cdev)
204{
205 sensors_cdev->dev = device_create(sensors_class, parent, 0,
206 sensors_cdev, "%s", sensors_cdev->name);
207 if (IS_ERR(sensors_cdev->dev))
208 return PTR_ERR(sensors_cdev->dev);
209
210 down_write(&sensors_list_lock);
211 list_add_tail(&sensors_cdev->node, &sensors_list);
212 up_write(&sensors_list_lock);
213
214 pr_debug("Registered sensors device: %s\n",
215 sensors_cdev->name);
216 return 0;
217}
218EXPORT_SYMBOL(sensors_classdev_register);
219
220/**
221 * sensors_classdev_unregister - unregister a object of sensors class.
222 * @sensors_cdev: the sensor device to unregister
223 * Unregister a previously registered via sensors_classdev_register object.
224*/
225void sensors_classdev_unregister(struct sensors_classdev *sensors_cdev)
226{
227 device_unregister(sensors_cdev->dev);
228 down_write(&sensors_list_lock);
229 list_del(&sensors_cdev->node);
230 up_write(&sensors_list_lock);
231}
232EXPORT_SYMBOL(sensors_classdev_unregister);
233
234static int __init sensors_init(void)
235{
236 sensors_class = class_create(THIS_MODULE, "sensors");
237 if (IS_ERR(sensors_class))
238 return PTR_ERR(sensors_class);
239 sensors_class->dev_attrs = sensors_class_attrs;
240 return 0;
241}
242
243static void __exit sensors_exit(void)
244{
245 class_destroy(sensors_class);
246}
247
248subsys_initcall(sensors_init);
249module_exit(sensors_exit);