linux/drivers/iio/position/hid-sensor-custom-intel-hinge.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * HID Sensors Driver
   4 * Copyright (c) 2020, Intel Corporation.
   5 */
   6#include <linux/hid-sensor-hub.h>
   7#include <linux/iio/buffer.h>
   8#include <linux/iio/iio.h>
   9#include <linux/platform_device.h>
  10
  11#include "../common/hid-sensors/hid-sensor-trigger.h"
  12
  13enum hinge_channel {
  14        CHANNEL_SCAN_INDEX_HINGE_ANGLE,
  15        CHANNEL_SCAN_INDEX_SCREEN_ANGLE,
  16        CHANNEL_SCAN_INDEX_KEYBOARD_ANGLE,
  17        CHANNEL_SCAN_INDEX_MAX,
  18};
  19
  20#define CHANNEL_SCAN_INDEX_TIMESTAMP CHANNEL_SCAN_INDEX_MAX
  21
  22static const u32 hinge_addresses[CHANNEL_SCAN_INDEX_MAX] = {
  23        HID_USAGE_SENSOR_DATA_FIELD_CUSTOM_VALUE(1),
  24        HID_USAGE_SENSOR_DATA_FIELD_CUSTOM_VALUE(2),
  25        HID_USAGE_SENSOR_DATA_FIELD_CUSTOM_VALUE(3)
  26};
  27
  28static const char *const hinge_labels[CHANNEL_SCAN_INDEX_MAX] = { "hinge",
  29                                                                  "screen",
  30                                                                  "keyboard" };
  31
  32struct hinge_state {
  33        struct iio_dev *indio_dev;
  34        struct hid_sensor_hub_attribute_info hinge[CHANNEL_SCAN_INDEX_MAX];
  35        struct hid_sensor_hub_callbacks callbacks;
  36        struct hid_sensor_common common_attributes;
  37        const char *labels[CHANNEL_SCAN_INDEX_MAX];
  38        struct {
  39                u32 hinge_val[3];
  40                u64 timestamp __aligned(8);
  41        } scan;
  42
  43        int scale_pre_decml;
  44        int scale_post_decml;
  45        int scale_precision;
  46        int value_offset;
  47        u64 timestamp;
  48};
  49
  50static const u32 hinge_sensitivity_addresses[] = {
  51        HID_USAGE_SENSOR_DATA_FIELD_CUSTOM_VALUE(1),
  52};
  53
  54/* Channel definitions */
  55static const struct iio_chan_spec hinge_channels[] = {
  56        {
  57                .type = IIO_ANGL,
  58                .indexed = 1,
  59                .channel = 0,
  60                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
  61                .info_mask_shared_by_type =
  62                        BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE) |
  63                        BIT(IIO_CHAN_INFO_SAMP_FREQ) | BIT(IIO_CHAN_INFO_HYSTERESIS),
  64                .scan_index = CHANNEL_SCAN_INDEX_HINGE_ANGLE,
  65                .scan_type = {
  66                        .sign = 's',
  67                        .storagebits = 32,
  68                },
  69        }, {
  70                .type = IIO_ANGL,
  71                .indexed = 1,
  72                .channel = 1,
  73                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
  74                .info_mask_shared_by_type =
  75                        BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE) |
  76                        BIT(IIO_CHAN_INFO_SAMP_FREQ) | BIT(IIO_CHAN_INFO_HYSTERESIS),
  77                .scan_index = CHANNEL_SCAN_INDEX_SCREEN_ANGLE,
  78                .scan_type = {
  79                        .sign = 's',
  80                        .storagebits = 32,
  81                },
  82        }, {
  83                .type = IIO_ANGL,
  84                .indexed = 1,
  85                .channel = 2,
  86                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
  87                .info_mask_shared_by_type =
  88                        BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE) |
  89                        BIT(IIO_CHAN_INFO_SAMP_FREQ) | BIT(IIO_CHAN_INFO_HYSTERESIS),
  90                .scan_index = CHANNEL_SCAN_INDEX_KEYBOARD_ANGLE,
  91                .scan_type = {
  92                        .sign = 's',
  93                        .storagebits = 32,
  94                },
  95        },
  96        IIO_CHAN_SOFT_TIMESTAMP(CHANNEL_SCAN_INDEX_TIMESTAMP)
  97};
  98
  99/* Adjust channel real bits based on report descriptor */
 100static void hinge_adjust_channel_realbits(struct iio_chan_spec *channels,
 101                                          int channel, int size)
 102{
 103        channels[channel].scan_type.realbits = size * 8;
 104}
 105
 106/* Channel read_raw handler */
 107static int hinge_read_raw(struct iio_dev *indio_dev,
 108                          struct iio_chan_spec const *chan, int *val, int *val2,
 109                          long mask)
 110{
 111        struct hinge_state *st = iio_priv(indio_dev);
 112        struct hid_sensor_hub_device *hsdev;
 113        int report_id;
 114        s32 min;
 115
 116        hsdev = st->common_attributes.hsdev;
 117        switch (mask) {
 118        case IIO_CHAN_INFO_RAW:
 119                hid_sensor_power_state(&st->common_attributes, true);
 120                report_id = st->hinge[chan->scan_index].report_id;
 121                min = st->hinge[chan->scan_index].logical_minimum;
 122                if (report_id < 0) {
 123                        hid_sensor_power_state(&st->common_attributes, false);
 124                        return -EINVAL;
 125                }
 126
 127                *val = sensor_hub_input_attr_get_raw_value(st->common_attributes.hsdev,
 128                                                           hsdev->usage,
 129                                                           hinge_addresses[chan->scan_index],
 130                                                           report_id,
 131                                                           SENSOR_HUB_SYNC, min < 0);
 132
 133                hid_sensor_power_state(&st->common_attributes, false);
 134                return IIO_VAL_INT;
 135        case IIO_CHAN_INFO_SCALE:
 136                *val = st->scale_pre_decml;
 137                *val2 = st->scale_post_decml;
 138                return st->scale_precision;
 139        case IIO_CHAN_INFO_OFFSET:
 140                *val = st->value_offset;
 141                return IIO_VAL_INT;
 142        case IIO_CHAN_INFO_SAMP_FREQ:
 143                return hid_sensor_read_samp_freq_value(&st->common_attributes,
 144                                                       val, val2);
 145        case IIO_CHAN_INFO_HYSTERESIS:
 146                return hid_sensor_read_raw_hyst_value(&st->common_attributes,
 147                                                      val, val2);
 148        default:
 149                return -EINVAL;
 150        }
 151}
 152
 153/* Channel write_raw handler */
 154static int hinge_write_raw(struct iio_dev *indio_dev,
 155                           struct iio_chan_spec const *chan, int val, int val2,
 156                           long mask)
 157{
 158        struct hinge_state *st = iio_priv(indio_dev);
 159
 160        switch (mask) {
 161        case IIO_CHAN_INFO_SAMP_FREQ:
 162                return hid_sensor_write_samp_freq_value(&st->common_attributes,
 163                                                        val, val2);
 164        case IIO_CHAN_INFO_HYSTERESIS:
 165                return hid_sensor_write_raw_hyst_value(&st->common_attributes,
 166                                                       val, val2);
 167        default:
 168                return -EINVAL;
 169        }
 170}
 171
 172static int hinge_read_label(struct iio_dev *indio_dev,
 173                            struct iio_chan_spec const *chan, char *label)
 174{
 175        struct hinge_state *st = iio_priv(indio_dev);
 176
 177        return sprintf(label, "%s\n", st->labels[chan->channel]);
 178}
 179
 180static const struct iio_info hinge_info = {
 181        .read_raw = hinge_read_raw,
 182        .write_raw = hinge_write_raw,
 183        .read_label = hinge_read_label,
 184};
 185
 186/*
 187 * Callback handler to send event after all samples are received
 188 * and captured.
 189 */
 190static int hinge_proc_event(struct hid_sensor_hub_device *hsdev,
 191                            unsigned int usage_id, void *priv)
 192{
 193        struct iio_dev *indio_dev = platform_get_drvdata(priv);
 194        struct hinge_state *st = iio_priv(indio_dev);
 195
 196        if (atomic_read(&st->common_attributes.data_ready)) {
 197                if (!st->timestamp)
 198                        st->timestamp = iio_get_time_ns(indio_dev);
 199
 200                iio_push_to_buffers_with_timestamp(indio_dev, &st->scan,
 201                                                   st->timestamp);
 202
 203                st->timestamp = 0;
 204        }
 205        return 0;
 206}
 207
 208/* Capture samples in local storage */
 209static int hinge_capture_sample(struct hid_sensor_hub_device *hsdev,
 210                                unsigned int usage_id, size_t raw_len,
 211                                char *raw_data, void *priv)
 212{
 213        struct iio_dev *indio_dev = platform_get_drvdata(priv);
 214        struct hinge_state *st = iio_priv(indio_dev);
 215        int offset;
 216
 217        switch (usage_id) {
 218        case HID_USAGE_SENSOR_DATA_FIELD_CUSTOM_VALUE(1):
 219        case HID_USAGE_SENSOR_DATA_FIELD_CUSTOM_VALUE(2):
 220        case HID_USAGE_SENSOR_DATA_FIELD_CUSTOM_VALUE(3):
 221                offset = usage_id - HID_USAGE_SENSOR_DATA_FIELD_CUSTOM_VALUE(1);
 222                st->scan.hinge_val[offset] = *(u32 *)raw_data;
 223                return 0;
 224        case HID_USAGE_SENSOR_TIME_TIMESTAMP:
 225                st->timestamp = hid_sensor_convert_timestamp(&st->common_attributes,
 226                                                             *(int64_t *)raw_data);
 227                return 0;
 228        default:
 229                return -EINVAL;
 230        }
 231}
 232
 233/* Parse report which is specific to an usage id */
 234static int hinge_parse_report(struct platform_device *pdev,
 235                              struct hid_sensor_hub_device *hsdev,
 236                              struct iio_chan_spec *channels,
 237                              unsigned int usage_id, struct hinge_state *st)
 238{
 239        int ret;
 240        int i;
 241
 242        for (i = 0; i < CHANNEL_SCAN_INDEX_MAX; ++i) {
 243                ret = sensor_hub_input_get_attribute_info(hsdev,
 244                                                          HID_INPUT_REPORT,
 245                                                          usage_id,
 246                                                          hinge_addresses[i],
 247                                                          &st->hinge[i]);
 248                if (ret < 0)
 249                        return ret;
 250
 251                hinge_adjust_channel_realbits(channels, i, st->hinge[i].size);
 252        }
 253
 254        st->scale_precision = hid_sensor_format_scale(HID_USAGE_SENSOR_HINGE,
 255                        &st->hinge[CHANNEL_SCAN_INDEX_HINGE_ANGLE],
 256                        &st->scale_pre_decml, &st->scale_post_decml);
 257
 258        return ret;
 259}
 260
 261/* Function to initialize the processing for usage id */
 262static int hid_hinge_probe(struct platform_device *pdev)
 263{
 264        struct hinge_state *st;
 265        struct iio_dev *indio_dev;
 266        struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
 267        int ret;
 268        int i;
 269
 270        indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
 271        if (!indio_dev)
 272                return -ENOMEM;
 273
 274        platform_set_drvdata(pdev, indio_dev);
 275
 276        st = iio_priv(indio_dev);
 277        st->common_attributes.hsdev = hsdev;
 278        st->common_attributes.pdev = pdev;
 279        st->indio_dev = indio_dev;
 280        for (i = 0; i < CHANNEL_SCAN_INDEX_MAX; i++)
 281                st->labels[i] = hinge_labels[i];
 282
 283        ret = hid_sensor_parse_common_attributes(hsdev, hsdev->usage,
 284                                                 &st->common_attributes,
 285                                                 hinge_sensitivity_addresses,
 286                                                 ARRAY_SIZE(hinge_sensitivity_addresses));
 287        if (ret) {
 288                dev_err(&pdev->dev, "failed to setup common attributes\n");
 289                return ret;
 290        }
 291
 292        indio_dev->num_channels = ARRAY_SIZE(hinge_channels);
 293        indio_dev->channels = devm_kmemdup(&indio_dev->dev, hinge_channels,
 294                                           sizeof(hinge_channels), GFP_KERNEL);
 295        if (!indio_dev->channels)
 296                return -ENOMEM;
 297
 298        ret = hinge_parse_report(pdev, hsdev,
 299                                 (struct iio_chan_spec *)indio_dev->channels,
 300                                 hsdev->usage, st);
 301        if (ret) {
 302                dev_err(&pdev->dev, "failed to setup attributes\n");
 303                return ret;
 304        }
 305
 306        indio_dev->dev.parent = &pdev->dev;
 307        indio_dev->info = &hinge_info;
 308        indio_dev->name = "hinge";
 309        indio_dev->modes = INDIO_DIRECT_MODE;
 310
 311        atomic_set(&st->common_attributes.data_ready, 0);
 312        ret = hid_sensor_setup_trigger(indio_dev, indio_dev->name,
 313                                       &st->common_attributes);
 314        if (ret < 0) {
 315                dev_err(&pdev->dev, "trigger setup failed\n");
 316                return ret;
 317        }
 318
 319        st->callbacks.send_event = hinge_proc_event;
 320        st->callbacks.capture_sample = hinge_capture_sample;
 321        st->callbacks.pdev = pdev;
 322        ret = sensor_hub_register_callback(hsdev, hsdev->usage, &st->callbacks);
 323        if (ret < 0) {
 324                dev_err(&pdev->dev, "callback reg failed\n");
 325                goto error_remove_trigger;
 326        }
 327
 328        ret = iio_device_register(indio_dev);
 329        if (ret) {
 330                dev_err(&pdev->dev, "device register failed\n");
 331                goto error_remove_callback;
 332        }
 333
 334        return ret;
 335
 336error_remove_callback:
 337        sensor_hub_remove_callback(hsdev, hsdev->usage);
 338error_remove_trigger:
 339        hid_sensor_remove_trigger(indio_dev, &st->common_attributes);
 340        return ret;
 341}
 342
 343/* Function to deinitialize the processing for usage id */
 344static int hid_hinge_remove(struct platform_device *pdev)
 345{
 346        struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
 347        struct iio_dev *indio_dev = platform_get_drvdata(pdev);
 348        struct hinge_state *st = iio_priv(indio_dev);
 349
 350        iio_device_unregister(indio_dev);
 351        sensor_hub_remove_callback(hsdev, hsdev->usage);
 352        hid_sensor_remove_trigger(indio_dev, &st->common_attributes);
 353
 354        return 0;
 355}
 356
 357static const struct platform_device_id hid_hinge_ids[] = {
 358        {
 359                /* Format: HID-SENSOR-INT-usage_id_in_hex_lowercase */
 360                .name = "HID-SENSOR-INT-020b",
 361        },
 362        { /* sentinel */ }
 363};
 364MODULE_DEVICE_TABLE(platform, hid_hinge_ids);
 365
 366static struct platform_driver hid_hinge_platform_driver = {
 367        .id_table = hid_hinge_ids,
 368        .driver = {
 369                .name   = KBUILD_MODNAME,
 370                .pm     = &hid_sensor_pm_ops,
 371        },
 372        .probe          = hid_hinge_probe,
 373        .remove         = hid_hinge_remove,
 374};
 375module_platform_driver(hid_hinge_platform_driver);
 376
 377MODULE_DESCRIPTION("HID Sensor INTEL Hinge");
 378MODULE_AUTHOR("Ye Xiang <xiang.ye@intel.com>");
 379MODULE_LICENSE("GPL");
 380