cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

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);