rtc-hid-sensor-time.c (9219B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * HID Sensor Time Driver 4 * Copyright (c) 2012, Alexander Holler. 5 */ 6#include <linux/device.h> 7#include <linux/platform_device.h> 8#include <linux/module.h> 9#include <linux/hid-sensor-hub.h> 10#include <linux/iio/iio.h> 11#include <linux/rtc.h> 12 13enum hid_time_channel { 14 CHANNEL_SCAN_INDEX_YEAR, 15 CHANNEL_SCAN_INDEX_MONTH, 16 CHANNEL_SCAN_INDEX_DAY, 17 CHANNEL_SCAN_INDEX_HOUR, 18 CHANNEL_SCAN_INDEX_MINUTE, 19 CHANNEL_SCAN_INDEX_SECOND, 20 TIME_RTC_CHANNEL_MAX, 21}; 22 23struct hid_time_state { 24 struct hid_sensor_hub_callbacks callbacks; 25 struct hid_sensor_common common_attributes; 26 struct hid_sensor_hub_attribute_info info[TIME_RTC_CHANNEL_MAX]; 27 struct rtc_time last_time; 28 spinlock_t lock_last_time; 29 struct completion comp_last_time; 30 struct rtc_time time_buf; 31 struct rtc_device *rtc; 32}; 33 34static const u32 hid_time_addresses[TIME_RTC_CHANNEL_MAX] = { 35 HID_USAGE_SENSOR_TIME_YEAR, 36 HID_USAGE_SENSOR_TIME_MONTH, 37 HID_USAGE_SENSOR_TIME_DAY, 38 HID_USAGE_SENSOR_TIME_HOUR, 39 HID_USAGE_SENSOR_TIME_MINUTE, 40 HID_USAGE_SENSOR_TIME_SECOND, 41}; 42 43/* Channel names for verbose error messages */ 44static const char * const hid_time_channel_names[TIME_RTC_CHANNEL_MAX] = { 45 "year", "month", "day", "hour", "minute", "second", 46}; 47 48/* Callback handler to send event after all samples are received and captured */ 49static int hid_time_proc_event(struct hid_sensor_hub_device *hsdev, 50 unsigned usage_id, void *priv) 51{ 52 unsigned long flags; 53 struct hid_time_state *time_state = platform_get_drvdata(priv); 54 55 spin_lock_irqsave(&time_state->lock_last_time, flags); 56 time_state->last_time = time_state->time_buf; 57 spin_unlock_irqrestore(&time_state->lock_last_time, flags); 58 complete(&time_state->comp_last_time); 59 return 0; 60} 61 62static u32 hid_time_value(size_t raw_len, char *raw_data) 63{ 64 switch (raw_len) { 65 case 1: 66 return *(u8 *)raw_data; 67 case 2: 68 return *(u16 *)raw_data; 69 case 4: 70 return *(u32 *)raw_data; 71 default: 72 return (u32)(~0U); /* 0xff... or -1 to denote an error */ 73 } 74} 75 76static int hid_time_capture_sample(struct hid_sensor_hub_device *hsdev, 77 unsigned usage_id, size_t raw_len, 78 char *raw_data, void *priv) 79{ 80 struct hid_time_state *time_state = platform_get_drvdata(priv); 81 struct rtc_time *time_buf = &time_state->time_buf; 82 83 switch (usage_id) { 84 case HID_USAGE_SENSOR_TIME_YEAR: 85 /* 86 * The draft for HID-sensors (HUTRR39) currently doesn't define 87 * the range for the year attribute. Therefor we support 88 * 8 bit (0-99) and 16 or 32 bits (full) as size for the year. 89 */ 90 if (raw_len == 1) { 91 time_buf->tm_year = *(u8 *)raw_data; 92 if (time_buf->tm_year < 70) 93 /* assume we are in 1970...2069 */ 94 time_buf->tm_year += 100; 95 } else 96 time_buf->tm_year = 97 (int)hid_time_value(raw_len, raw_data)-1900; 98 break; 99 case HID_USAGE_SENSOR_TIME_MONTH: 100 /* sensors are sending the month as 1-12, we need 0-11 */ 101 time_buf->tm_mon = (int)hid_time_value(raw_len, raw_data)-1; 102 break; 103 case HID_USAGE_SENSOR_TIME_DAY: 104 time_buf->tm_mday = (int)hid_time_value(raw_len, raw_data); 105 break; 106 case HID_USAGE_SENSOR_TIME_HOUR: 107 time_buf->tm_hour = (int)hid_time_value(raw_len, raw_data); 108 break; 109 case HID_USAGE_SENSOR_TIME_MINUTE: 110 time_buf->tm_min = (int)hid_time_value(raw_len, raw_data); 111 break; 112 case HID_USAGE_SENSOR_TIME_SECOND: 113 time_buf->tm_sec = (int)hid_time_value(raw_len, raw_data); 114 break; 115 default: 116 return -EINVAL; 117 } 118 return 0; 119} 120 121/* small helper, haven't found any other way */ 122static const char *hid_time_attrib_name(u32 attrib_id) 123{ 124 static const char unknown[] = "unknown"; 125 unsigned i; 126 127 for (i = 0; i < TIME_RTC_CHANNEL_MAX; ++i) { 128 if (hid_time_addresses[i] == attrib_id) 129 return hid_time_channel_names[i]; 130 } 131 return unknown; /* should never happen */ 132} 133 134static int hid_time_parse_report(struct platform_device *pdev, 135 struct hid_sensor_hub_device *hsdev, 136 unsigned usage_id, 137 struct hid_time_state *time_state) 138{ 139 int report_id, i; 140 141 for (i = 0; i < TIME_RTC_CHANNEL_MAX; ++i) 142 if (sensor_hub_input_get_attribute_info(hsdev, 143 HID_INPUT_REPORT, usage_id, 144 hid_time_addresses[i], 145 &time_state->info[i]) < 0) 146 return -EINVAL; 147 /* Check the (needed) attributes for sanity */ 148 report_id = time_state->info[0].report_id; 149 if (report_id < 0) { 150 dev_err(&pdev->dev, "bad report ID!\n"); 151 return -EINVAL; 152 } 153 for (i = 0; i < TIME_RTC_CHANNEL_MAX; ++i) { 154 if (time_state->info[i].report_id != report_id) { 155 dev_err(&pdev->dev, 156 "not all needed attributes inside the same report!\n"); 157 return -EINVAL; 158 } 159 if (time_state->info[i].size == 3 || 160 time_state->info[i].size > 4) { 161 dev_err(&pdev->dev, 162 "attribute '%s' not 8, 16 or 32 bits wide!\n", 163 hid_time_attrib_name( 164 time_state->info[i].attrib_id)); 165 return -EINVAL; 166 } 167 if (time_state->info[i].units != 168 HID_USAGE_SENSOR_UNITS_NOT_SPECIFIED && 169 /* allow attribute seconds with unit seconds */ 170 !(time_state->info[i].attrib_id == 171 HID_USAGE_SENSOR_TIME_SECOND && 172 time_state->info[i].units == 173 HID_USAGE_SENSOR_UNITS_SECOND)) { 174 dev_err(&pdev->dev, 175 "attribute '%s' hasn't a unit of type 'none'!\n", 176 hid_time_attrib_name( 177 time_state->info[i].attrib_id)); 178 return -EINVAL; 179 } 180 if (time_state->info[i].unit_expo) { 181 dev_err(&pdev->dev, 182 "attribute '%s' hasn't a unit exponent of 1!\n", 183 hid_time_attrib_name( 184 time_state->info[i].attrib_id)); 185 return -EINVAL; 186 } 187 } 188 189 return 0; 190} 191 192static int hid_rtc_read_time(struct device *dev, struct rtc_time *tm) 193{ 194 unsigned long flags; 195 struct hid_time_state *time_state = dev_get_drvdata(dev); 196 int ret; 197 198 reinit_completion(&time_state->comp_last_time); 199 /* get a report with all values through requesting one value */ 200 sensor_hub_input_attr_get_raw_value(time_state->common_attributes.hsdev, 201 HID_USAGE_SENSOR_TIME, hid_time_addresses[0], 202 time_state->info[0].report_id, SENSOR_HUB_SYNC, false); 203 /* wait for all values (event) */ 204 ret = wait_for_completion_killable_timeout( 205 &time_state->comp_last_time, HZ*6); 206 if (ret > 0) { 207 /* no error */ 208 spin_lock_irqsave(&time_state->lock_last_time, flags); 209 *tm = time_state->last_time; 210 spin_unlock_irqrestore(&time_state->lock_last_time, flags); 211 return 0; 212 } 213 if (!ret) 214 return -EIO; /* timeouted */ 215 return ret; /* killed (-ERESTARTSYS) */ 216} 217 218static const struct rtc_class_ops hid_time_rtc_ops = { 219 .read_time = hid_rtc_read_time, 220}; 221 222static int hid_time_probe(struct platform_device *pdev) 223{ 224 int ret = 0; 225 struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev); 226 struct hid_time_state *time_state = devm_kzalloc(&pdev->dev, 227 sizeof(struct hid_time_state), GFP_KERNEL); 228 229 if (time_state == NULL) 230 return -ENOMEM; 231 232 platform_set_drvdata(pdev, time_state); 233 234 spin_lock_init(&time_state->lock_last_time); 235 init_completion(&time_state->comp_last_time); 236 time_state->common_attributes.hsdev = hsdev; 237 time_state->common_attributes.pdev = pdev; 238 239 ret = hid_sensor_parse_common_attributes(hsdev, 240 HID_USAGE_SENSOR_TIME, 241 &time_state->common_attributes, 242 NULL, 243 0); 244 if (ret) { 245 dev_err(&pdev->dev, "failed to setup common attributes!\n"); 246 return ret; 247 } 248 249 ret = hid_time_parse_report(pdev, hsdev, HID_USAGE_SENSOR_TIME, 250 time_state); 251 if (ret) { 252 dev_err(&pdev->dev, "failed to setup attributes!\n"); 253 return ret; 254 } 255 256 time_state->callbacks.send_event = hid_time_proc_event; 257 time_state->callbacks.capture_sample = hid_time_capture_sample; 258 time_state->callbacks.pdev = pdev; 259 ret = sensor_hub_register_callback(hsdev, HID_USAGE_SENSOR_TIME, 260 &time_state->callbacks); 261 if (ret < 0) { 262 dev_err(&pdev->dev, "register callback failed!\n"); 263 return ret; 264 } 265 266 ret = sensor_hub_device_open(hsdev); 267 if (ret) { 268 dev_err(&pdev->dev, "failed to open sensor hub device!\n"); 269 goto err_open; 270 } 271 272 /* 273 * Enable HID input processing early in order to be able to read the 274 * clock already in devm_rtc_device_register(). 275 */ 276 hid_device_io_start(hsdev->hdev); 277 278 time_state->rtc = devm_rtc_device_register(&pdev->dev, 279 "hid-sensor-time", &hid_time_rtc_ops, 280 THIS_MODULE); 281 282 if (IS_ERR(time_state->rtc)) { 283 hid_device_io_stop(hsdev->hdev); 284 ret = PTR_ERR(time_state->rtc); 285 time_state->rtc = NULL; 286 dev_err(&pdev->dev, "rtc device register failed!\n"); 287 goto err_rtc; 288 } 289 290 return ret; 291 292err_rtc: 293 sensor_hub_device_close(hsdev); 294err_open: 295 sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TIME); 296 return ret; 297} 298 299static int hid_time_remove(struct platform_device *pdev) 300{ 301 struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev); 302 303 sensor_hub_device_close(hsdev); 304 sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TIME); 305 306 return 0; 307} 308 309static const struct platform_device_id hid_time_ids[] = { 310 { 311 /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ 312 .name = "HID-SENSOR-2000a0", 313 }, 314 { /* sentinel */ } 315}; 316MODULE_DEVICE_TABLE(platform, hid_time_ids); 317 318static struct platform_driver hid_time_platform_driver = { 319 .id_table = hid_time_ids, 320 .driver = { 321 .name = KBUILD_MODNAME, 322 }, 323 .probe = hid_time_probe, 324 .remove = hid_time_remove, 325}; 326module_platform_driver(hid_time_platform_driver); 327 328MODULE_DESCRIPTION("HID Sensor Time"); 329MODULE_AUTHOR("Alexander Holler <holler@ahsoftware.de>"); 330MODULE_LICENSE("GPL"); 331MODULE_IMPORT_NS(IIO_HID);