2 * HID Sensor Time Driver
3 * Copyright (c) 2012, Alexander Holler.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
19 #include <linux/device.h>
20 #include <linux/platform_device.h>
21 #include <linux/module.h>
22 #include <linux/hid-sensor-hub.h>
23 #include <linux/iio/iio.h>
24 #include <linux/rtc.h>
26 /* Format: HID-SENSOR-usage_id_in_hex */
27 /* Usage ID from spec for Time: 0x2000A0 */
28 #define DRIVER_NAME "HID-SENSOR-2000a0" /* must be lowercase */
30 enum hid_time_channel
{
31 CHANNEL_SCAN_INDEX_YEAR
,
32 CHANNEL_SCAN_INDEX_MONTH
,
33 CHANNEL_SCAN_INDEX_DAY
,
34 CHANNEL_SCAN_INDEX_HOUR
,
35 CHANNEL_SCAN_INDEX_MINUTE
,
36 CHANNEL_SCAN_INDEX_SECOND
,
40 struct hid_time_state
{
41 struct hid_sensor_hub_callbacks callbacks
;
42 struct hid_sensor_common common_attributes
;
43 struct hid_sensor_hub_attribute_info info
[TIME_RTC_CHANNEL_MAX
];
44 struct rtc_time last_time
;
45 spinlock_t lock_last_time
;
46 struct completion comp_last_time
;
47 struct rtc_time time_buf
;
48 struct rtc_device
*rtc
;
51 static const u32 hid_time_addresses
[TIME_RTC_CHANNEL_MAX
] = {
52 HID_USAGE_SENSOR_TIME_YEAR
,
53 HID_USAGE_SENSOR_TIME_MONTH
,
54 HID_USAGE_SENSOR_TIME_DAY
,
55 HID_USAGE_SENSOR_TIME_HOUR
,
56 HID_USAGE_SENSOR_TIME_MINUTE
,
57 HID_USAGE_SENSOR_TIME_SECOND
,
60 /* Channel names for verbose error messages */
61 static const char * const hid_time_channel_names
[TIME_RTC_CHANNEL_MAX
] = {
62 "year", "month", "day", "hour", "minute", "second",
65 /* Callback handler to send event after all samples are received and captured */
66 static int hid_time_proc_event(struct hid_sensor_hub_device
*hsdev
,
67 unsigned usage_id
, void *priv
)
70 struct hid_time_state
*time_state
= platform_get_drvdata(priv
);
72 spin_lock_irqsave(&time_state
->lock_last_time
, flags
);
73 time_state
->last_time
= time_state
->time_buf
;
74 spin_unlock_irqrestore(&time_state
->lock_last_time
, flags
);
75 complete(&time_state
->comp_last_time
);
79 static int hid_time_capture_sample(struct hid_sensor_hub_device
*hsdev
,
80 unsigned usage_id
, size_t raw_len
,
81 char *raw_data
, void *priv
)
83 struct hid_time_state
*time_state
= platform_get_drvdata(priv
);
84 struct rtc_time
*time_buf
= &time_state
->time_buf
;
87 case HID_USAGE_SENSOR_TIME_YEAR
:
88 time_buf
->tm_year
= *(u8
*)raw_data
;
89 if (time_buf
->tm_year
< 70)
90 /* assume we are in 1970...2069 */
91 time_buf
->tm_year
+= 100;
93 case HID_USAGE_SENSOR_TIME_MONTH
:
94 /* sensor sending the month as 1-12, we need 0-11 */
95 time_buf
->tm_mon
= *(u8
*)raw_data
-1;
97 case HID_USAGE_SENSOR_TIME_DAY
:
98 time_buf
->tm_mday
= *(u8
*)raw_data
;
100 case HID_USAGE_SENSOR_TIME_HOUR
:
101 time_buf
->tm_hour
= *(u8
*)raw_data
;
103 case HID_USAGE_SENSOR_TIME_MINUTE
:
104 time_buf
->tm_min
= *(u8
*)raw_data
;
106 case HID_USAGE_SENSOR_TIME_SECOND
:
107 time_buf
->tm_sec
= *(u8
*)raw_data
;
115 /* small helper, haven't found any other way */
116 static const char *hid_time_attrib_name(u32 attrib_id
)
118 static const char unknown
[] = "unknown";
121 for (i
= 0; i
< TIME_RTC_CHANNEL_MAX
; ++i
) {
122 if (hid_time_addresses
[i
] == attrib_id
)
123 return hid_time_channel_names
[i
];
125 return unknown
; /* should never happen */
128 static int hid_time_parse_report(struct platform_device
*pdev
,
129 struct hid_sensor_hub_device
*hsdev
,
131 struct hid_time_state
*time_state
)
135 for (i
= 0; i
< TIME_RTC_CHANNEL_MAX
; ++i
)
136 if (sensor_hub_input_get_attribute_info(hsdev
,
137 HID_INPUT_REPORT
, usage_id
,
138 hid_time_addresses
[i
],
139 &time_state
->info
[i
]) < 0)
141 /* Check the (needed) attributes for sanity */
142 report_id
= time_state
->info
[0].report_id
;
144 dev_err(&pdev
->dev
, "bad report ID!\n");
147 for (i
= 0; i
< TIME_RTC_CHANNEL_MAX
; ++i
) {
148 if (time_state
->info
[i
].report_id
!= report_id
) {
150 "not all needed attributes inside the same report!\n");
153 if (time_state
->info
[i
].size
!= 1) {
155 "attribute '%s' not 8 bits wide!\n",
156 hid_time_attrib_name(
157 time_state
->info
[i
].attrib_id
));
160 if (time_state
->info
[i
].units
!=
161 HID_USAGE_SENSOR_UNITS_NOT_SPECIFIED
&&
162 /* allow attribute seconds with unit seconds */
163 !(time_state
->info
[i
].attrib_id
==
164 HID_USAGE_SENSOR_TIME_SECOND
&&
165 time_state
->info
[i
].units
==
166 HID_USAGE_SENSOR_UNITS_SECOND
)) {
168 "attribute '%s' hasn't a unit of type 'none'!\n",
169 hid_time_attrib_name(
170 time_state
->info
[i
].attrib_id
));
173 if (time_state
->info
[i
].unit_expo
) {
175 "attribute '%s' hasn't a unit exponent of 1!\n",
176 hid_time_attrib_name(
177 time_state
->info
[i
].attrib_id
));
185 static int hid_rtc_read_time(struct device
*dev
, struct rtc_time
*tm
)
188 struct hid_time_state
*time_state
=
189 platform_get_drvdata(to_platform_device(dev
));
192 INIT_COMPLETION(time_state
->comp_last_time
);
193 /* get a report with all values through requesting one value */
194 sensor_hub_input_attr_get_raw_value(time_state
->common_attributes
.hsdev
,
195 HID_USAGE_SENSOR_TIME
, hid_time_addresses
[0],
196 time_state
->info
[0].report_id
);
197 /* wait for all values (event) */
198 ret
= wait_for_completion_killable_timeout(
199 &time_state
->comp_last_time
, HZ
*6);
202 spin_lock_irqsave(&time_state
->lock_last_time
, flags
);
203 *tm
= time_state
->last_time
;
204 spin_unlock_irqrestore(&time_state
->lock_last_time
, flags
);
208 return -EIO
; /* timeouted */
209 return ret
; /* killed (-ERESTARTSYS) */
212 static const struct rtc_class_ops hid_time_rtc_ops
= {
213 .read_time
= hid_rtc_read_time
,
216 static int hid_time_probe(struct platform_device
*pdev
)
219 struct hid_sensor_hub_device
*hsdev
= pdev
->dev
.platform_data
;
220 struct hid_time_state
*time_state
= devm_kzalloc(&pdev
->dev
,
221 sizeof(struct hid_time_state
), GFP_KERNEL
);
223 if (time_state
== NULL
)
226 platform_set_drvdata(pdev
, time_state
);
228 spin_lock_init(&time_state
->lock_last_time
);
229 init_completion(&time_state
->comp_last_time
);
230 time_state
->common_attributes
.hsdev
= hsdev
;
231 time_state
->common_attributes
.pdev
= pdev
;
233 ret
= hid_sensor_parse_common_attributes(hsdev
,
234 HID_USAGE_SENSOR_TIME
,
235 &time_state
->common_attributes
);
237 dev_err(&pdev
->dev
, "failed to setup common attributes!\n");
241 ret
= hid_time_parse_report(pdev
, hsdev
, HID_USAGE_SENSOR_TIME
,
244 dev_err(&pdev
->dev
, "failed to setup attributes!\n");
248 time_state
->callbacks
.send_event
= hid_time_proc_event
;
249 time_state
->callbacks
.capture_sample
= hid_time_capture_sample
;
250 time_state
->callbacks
.pdev
= pdev
;
251 ret
= sensor_hub_register_callback(hsdev
, HID_USAGE_SENSOR_TIME
,
252 &time_state
->callbacks
);
254 dev_err(&pdev
->dev
, "register callback failed!\n");
258 time_state
->rtc
= devm_rtc_device_register(&pdev
->dev
,
259 "hid-sensor-time", &hid_time_rtc_ops
,
262 if (IS_ERR(time_state
->rtc
)) {
263 dev_err(&pdev
->dev
, "rtc device register failed!\n");
264 return PTR_ERR(time_state
->rtc
);
270 static int hid_time_remove(struct platform_device
*pdev
)
272 struct hid_sensor_hub_device
*hsdev
= pdev
->dev
.platform_data
;
274 sensor_hub_remove_callback(hsdev
, HID_USAGE_SENSOR_TIME
);
279 static struct platform_driver hid_time_platform_driver
= {
282 .owner
= THIS_MODULE
,
284 .probe
= hid_time_probe
,
285 .remove
= hid_time_remove
,
287 module_platform_driver(hid_time_platform_driver
);
289 MODULE_DESCRIPTION("HID Sensor Time");
290 MODULE_AUTHOR("Alexander Holler <holler@ahsoftware.de>");
291 MODULE_LICENSE("GPL");