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