Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * HID Sensor Time Driver
0004  * Copyright (c) 2012, Alexander Holler.
0005  */
0006 #include <linux/device.h>
0007 #include <linux/platform_device.h>
0008 #include <linux/module.h>
0009 #include <linux/hid-sensor-hub.h>
0010 #include <linux/iio/iio.h>
0011 #include <linux/rtc.h>
0012 
0013 enum hid_time_channel {
0014     CHANNEL_SCAN_INDEX_YEAR,
0015     CHANNEL_SCAN_INDEX_MONTH,
0016     CHANNEL_SCAN_INDEX_DAY,
0017     CHANNEL_SCAN_INDEX_HOUR,
0018     CHANNEL_SCAN_INDEX_MINUTE,
0019     CHANNEL_SCAN_INDEX_SECOND,
0020     TIME_RTC_CHANNEL_MAX,
0021 };
0022 
0023 struct hid_time_state {
0024     struct hid_sensor_hub_callbacks callbacks;
0025     struct hid_sensor_common common_attributes;
0026     struct hid_sensor_hub_attribute_info info[TIME_RTC_CHANNEL_MAX];
0027     struct rtc_time last_time;
0028     spinlock_t lock_last_time;
0029     struct completion comp_last_time;
0030     struct rtc_time time_buf;
0031     struct rtc_device *rtc;
0032 };
0033 
0034 static const u32 hid_time_addresses[TIME_RTC_CHANNEL_MAX] = {
0035     HID_USAGE_SENSOR_TIME_YEAR,
0036     HID_USAGE_SENSOR_TIME_MONTH,
0037     HID_USAGE_SENSOR_TIME_DAY,
0038     HID_USAGE_SENSOR_TIME_HOUR,
0039     HID_USAGE_SENSOR_TIME_MINUTE,
0040     HID_USAGE_SENSOR_TIME_SECOND,
0041 };
0042 
0043 /* Channel names for verbose error messages */
0044 static const char * const hid_time_channel_names[TIME_RTC_CHANNEL_MAX] = {
0045     "year", "month", "day", "hour", "minute", "second",
0046 };
0047 
0048 /* Callback handler to send event after all samples are received and captured */
0049 static int hid_time_proc_event(struct hid_sensor_hub_device *hsdev,
0050                 unsigned usage_id, void *priv)
0051 {
0052     unsigned long flags;
0053     struct hid_time_state *time_state = platform_get_drvdata(priv);
0054 
0055     spin_lock_irqsave(&time_state->lock_last_time, flags);
0056     time_state->last_time = time_state->time_buf;
0057     spin_unlock_irqrestore(&time_state->lock_last_time, flags);
0058     complete(&time_state->comp_last_time);
0059     return 0;
0060 }
0061 
0062 static u32 hid_time_value(size_t raw_len, char *raw_data)
0063 {
0064     switch (raw_len) {
0065     case 1:
0066         return *(u8 *)raw_data;
0067     case 2:
0068         return *(u16 *)raw_data;
0069     case 4:
0070         return *(u32 *)raw_data;
0071     default:
0072         return (u32)(~0U); /* 0xff... or -1 to denote an error */
0073     }
0074 }
0075 
0076 static int hid_time_capture_sample(struct hid_sensor_hub_device *hsdev,
0077                 unsigned usage_id, size_t raw_len,
0078                 char *raw_data, void *priv)
0079 {
0080     struct hid_time_state *time_state = platform_get_drvdata(priv);
0081     struct rtc_time *time_buf = &time_state->time_buf;
0082 
0083     switch (usage_id) {
0084     case HID_USAGE_SENSOR_TIME_YEAR:
0085         /*
0086          * The draft for HID-sensors (HUTRR39) currently doesn't define
0087          * the range for the year attribute. Therefor we support
0088          * 8 bit (0-99) and 16 or 32 bits (full) as size for the year.
0089          */
0090         if (raw_len == 1) {
0091             time_buf->tm_year = *(u8 *)raw_data;
0092             if (time_buf->tm_year < 70)
0093                 /* assume we are in 1970...2069 */
0094                 time_buf->tm_year += 100;
0095         } else
0096             time_buf->tm_year =
0097                 (int)hid_time_value(raw_len, raw_data)-1900;
0098         break;
0099     case HID_USAGE_SENSOR_TIME_MONTH:
0100         /* sensors are sending the month as 1-12, we need 0-11 */
0101         time_buf->tm_mon = (int)hid_time_value(raw_len, raw_data)-1;
0102         break;
0103     case HID_USAGE_SENSOR_TIME_DAY:
0104         time_buf->tm_mday = (int)hid_time_value(raw_len, raw_data);
0105         break;
0106     case HID_USAGE_SENSOR_TIME_HOUR:
0107         time_buf->tm_hour = (int)hid_time_value(raw_len, raw_data);
0108         break;
0109     case HID_USAGE_SENSOR_TIME_MINUTE:
0110         time_buf->tm_min = (int)hid_time_value(raw_len, raw_data);
0111         break;
0112     case HID_USAGE_SENSOR_TIME_SECOND:
0113         time_buf->tm_sec = (int)hid_time_value(raw_len, raw_data);
0114         break;
0115     default:
0116         return -EINVAL;
0117     }
0118     return 0;
0119 }
0120 
0121 /* small helper, haven't found any other way */
0122 static const char *hid_time_attrib_name(u32 attrib_id)
0123 {
0124     static const char unknown[] = "unknown";
0125     unsigned i;
0126 
0127     for (i = 0; i < TIME_RTC_CHANNEL_MAX; ++i) {
0128         if (hid_time_addresses[i] == attrib_id)
0129             return hid_time_channel_names[i];
0130     }
0131     return unknown; /* should never happen */
0132 }
0133 
0134 static int hid_time_parse_report(struct platform_device *pdev,
0135                 struct hid_sensor_hub_device *hsdev,
0136                 unsigned usage_id,
0137                 struct hid_time_state *time_state)
0138 {
0139     int report_id, i;
0140 
0141     for (i = 0; i < TIME_RTC_CHANNEL_MAX; ++i)
0142         if (sensor_hub_input_get_attribute_info(hsdev,
0143                 HID_INPUT_REPORT, usage_id,
0144                 hid_time_addresses[i],
0145                 &time_state->info[i]) < 0)
0146             return -EINVAL;
0147     /* Check the (needed) attributes for sanity */
0148     report_id = time_state->info[0].report_id;
0149     if (report_id < 0) {
0150         dev_err(&pdev->dev, "bad report ID!\n");
0151         return -EINVAL;
0152     }
0153     for (i = 0; i < TIME_RTC_CHANNEL_MAX; ++i) {
0154         if (time_state->info[i].report_id != report_id) {
0155             dev_err(&pdev->dev,
0156                 "not all needed attributes inside the same report!\n");
0157             return -EINVAL;
0158         }
0159         if (time_state->info[i].size == 3 ||
0160                 time_state->info[i].size > 4) {
0161             dev_err(&pdev->dev,
0162                 "attribute '%s' not 8, 16 or 32 bits wide!\n",
0163                 hid_time_attrib_name(
0164                     time_state->info[i].attrib_id));
0165             return -EINVAL;
0166         }
0167         if (time_state->info[i].units !=
0168                 HID_USAGE_SENSOR_UNITS_NOT_SPECIFIED &&
0169                 /* allow attribute seconds with unit seconds */
0170                 !(time_state->info[i].attrib_id ==
0171                 HID_USAGE_SENSOR_TIME_SECOND &&
0172                 time_state->info[i].units ==
0173                 HID_USAGE_SENSOR_UNITS_SECOND)) {
0174             dev_err(&pdev->dev,
0175                 "attribute '%s' hasn't a unit of type 'none'!\n",
0176                 hid_time_attrib_name(
0177                     time_state->info[i].attrib_id));
0178             return -EINVAL;
0179         }
0180         if (time_state->info[i].unit_expo) {
0181             dev_err(&pdev->dev,
0182                 "attribute '%s' hasn't a unit exponent of 1!\n",
0183                 hid_time_attrib_name(
0184                     time_state->info[i].attrib_id));
0185             return -EINVAL;
0186         }
0187     }
0188 
0189     return 0;
0190 }
0191 
0192 static int hid_rtc_read_time(struct device *dev, struct rtc_time *tm)
0193 {
0194     unsigned long flags;
0195     struct hid_time_state *time_state = dev_get_drvdata(dev);
0196     int ret;
0197 
0198     reinit_completion(&time_state->comp_last_time);
0199     /* get a report with all values through requesting one value */
0200     sensor_hub_input_attr_get_raw_value(time_state->common_attributes.hsdev,
0201             HID_USAGE_SENSOR_TIME, hid_time_addresses[0],
0202             time_state->info[0].report_id, SENSOR_HUB_SYNC, false);
0203     /* wait for all values (event) */
0204     ret = wait_for_completion_killable_timeout(
0205             &time_state->comp_last_time, HZ*6);
0206     if (ret > 0) {
0207         /* no error */
0208         spin_lock_irqsave(&time_state->lock_last_time, flags);
0209         *tm = time_state->last_time;
0210         spin_unlock_irqrestore(&time_state->lock_last_time, flags);
0211         return 0;
0212     }
0213     if (!ret)
0214         return -EIO; /* timeouted */
0215     return ret; /* killed (-ERESTARTSYS) */
0216 }
0217 
0218 static const struct rtc_class_ops hid_time_rtc_ops = {
0219     .read_time = hid_rtc_read_time,
0220 };
0221 
0222 static int hid_time_probe(struct platform_device *pdev)
0223 {
0224     int ret = 0;
0225     struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
0226     struct hid_time_state *time_state = devm_kzalloc(&pdev->dev,
0227         sizeof(struct hid_time_state), GFP_KERNEL);
0228 
0229     if (time_state == NULL)
0230         return -ENOMEM;
0231 
0232     platform_set_drvdata(pdev, time_state);
0233 
0234     spin_lock_init(&time_state->lock_last_time);
0235     init_completion(&time_state->comp_last_time);
0236     time_state->common_attributes.hsdev = hsdev;
0237     time_state->common_attributes.pdev = pdev;
0238 
0239     ret = hid_sensor_parse_common_attributes(hsdev,
0240                 HID_USAGE_SENSOR_TIME,
0241                 &time_state->common_attributes,
0242                 NULL,
0243                 0);
0244     if (ret) {
0245         dev_err(&pdev->dev, "failed to setup common attributes!\n");
0246         return ret;
0247     }
0248 
0249     ret = hid_time_parse_report(pdev, hsdev, HID_USAGE_SENSOR_TIME,
0250                     time_state);
0251     if (ret) {
0252         dev_err(&pdev->dev, "failed to setup attributes!\n");
0253         return ret;
0254     }
0255 
0256     time_state->callbacks.send_event = hid_time_proc_event;
0257     time_state->callbacks.capture_sample = hid_time_capture_sample;
0258     time_state->callbacks.pdev = pdev;
0259     ret = sensor_hub_register_callback(hsdev, HID_USAGE_SENSOR_TIME,
0260                     &time_state->callbacks);
0261     if (ret < 0) {
0262         dev_err(&pdev->dev, "register callback failed!\n");
0263         return ret;
0264     }
0265 
0266     ret = sensor_hub_device_open(hsdev);
0267     if (ret) {
0268         dev_err(&pdev->dev, "failed to open sensor hub device!\n");
0269         goto err_open;
0270     }
0271 
0272     /*
0273      * Enable HID input processing early in order to be able to read the
0274      * clock already in devm_rtc_device_register().
0275      */
0276     hid_device_io_start(hsdev->hdev);
0277 
0278     time_state->rtc = devm_rtc_device_register(&pdev->dev,
0279                     "hid-sensor-time", &hid_time_rtc_ops,
0280                     THIS_MODULE);
0281 
0282     if (IS_ERR(time_state->rtc)) {
0283         hid_device_io_stop(hsdev->hdev);
0284         ret = PTR_ERR(time_state->rtc);
0285         time_state->rtc = NULL;
0286         dev_err(&pdev->dev, "rtc device register failed!\n");
0287         goto err_rtc;
0288     }
0289 
0290     return ret;
0291 
0292 err_rtc:
0293     sensor_hub_device_close(hsdev);
0294 err_open:
0295     sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TIME);
0296     return ret;
0297 }
0298 
0299 static int hid_time_remove(struct platform_device *pdev)
0300 {
0301     struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
0302 
0303     sensor_hub_device_close(hsdev);
0304     sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TIME);
0305 
0306     return 0;
0307 }
0308 
0309 static const struct platform_device_id hid_time_ids[] = {
0310     {
0311         /* Format: HID-SENSOR-usage_id_in_hex_lowercase */
0312         .name = "HID-SENSOR-2000a0",
0313     },
0314     { /* sentinel */ }
0315 };
0316 MODULE_DEVICE_TABLE(platform, hid_time_ids);
0317 
0318 static struct platform_driver hid_time_platform_driver = {
0319     .id_table = hid_time_ids,
0320     .driver = {
0321         .name   = KBUILD_MODNAME,
0322     },
0323     .probe      = hid_time_probe,
0324     .remove     = hid_time_remove,
0325 };
0326 module_platform_driver(hid_time_platform_driver);
0327 
0328 MODULE_DESCRIPTION("HID Sensor Time");
0329 MODULE_AUTHOR("Alexander Holler <holler@ahsoftware.de>");
0330 MODULE_LICENSE("GPL");
0331 MODULE_IMPORT_NS(IIO_HID);