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