1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * HID Sensors Driver 4 * Copyright (c) 2012, Intel Corporation. 5 */ 6 #include <linux/bitops.h> 7 #include <linux/device.h> 8 #include <linux/platform_device.h> 9 #include <linux/module.h> 10 #include <linux/mod_devicetable.h> 11 #include <linux/slab.h> 12 #include <linux/hid-sensor-hub.h> 13 #include <linux/iio/iio.h> 14 #include <linux/iio/buffer.h> 15 #include "../common/hid-sensors/hid-sensor-trigger.h" 16 17 enum accel_3d_channel { 18 CHANNEL_SCAN_INDEX_X, 19 CHANNEL_SCAN_INDEX_Y, 20 CHANNEL_SCAN_INDEX_Z, 21 ACCEL_3D_CHANNEL_MAX, 22 }; 23 24 #define CHANNEL_SCAN_INDEX_TIMESTAMP ACCEL_3D_CHANNEL_MAX 25 struct accel_3d_state { 26 struct hid_sensor_hub_callbacks callbacks; 27 struct hid_sensor_common common_attributes; 28 struct hid_sensor_hub_attribute_info accel[ACCEL_3D_CHANNEL_MAX]; 29 /* Ensure timestamp is naturally aligned */ 30 struct { 31 u32 accel_val[3]; 32 aligned_s64 timestamp; 33 } scan; 34 int scale_pre_decml; 35 int scale_post_decml; 36 int scale_precision; 37 int value_offset; 38 int64_t timestamp; 39 }; 40 41 static const u32 accel_3d_addresses[ACCEL_3D_CHANNEL_MAX] = { 42 HID_USAGE_SENSOR_ACCEL_X_AXIS, 43 HID_USAGE_SENSOR_ACCEL_Y_AXIS, 44 HID_USAGE_SENSOR_ACCEL_Z_AXIS 45 }; 46 47 static const u32 accel_3d_sensitivity_addresses[] = { 48 HID_USAGE_SENSOR_DATA_ACCELERATION, 49 }; 50 51 /* Channel definitions */ 52 static const struct iio_chan_spec accel_3d_channels[] = { 53 { 54 .type = IIO_ACCEL, 55 .modified = 1, 56 .channel2 = IIO_MOD_X, 57 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 58 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | 59 BIT(IIO_CHAN_INFO_SCALE) | 60 BIT(IIO_CHAN_INFO_SAMP_FREQ) | 61 BIT(IIO_CHAN_INFO_HYSTERESIS), 62 .scan_index = CHANNEL_SCAN_INDEX_X, 63 }, { 64 .type = IIO_ACCEL, 65 .modified = 1, 66 .channel2 = IIO_MOD_Y, 67 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 68 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | 69 BIT(IIO_CHAN_INFO_SCALE) | 70 BIT(IIO_CHAN_INFO_SAMP_FREQ) | 71 BIT(IIO_CHAN_INFO_HYSTERESIS), 72 .scan_index = CHANNEL_SCAN_INDEX_Y, 73 }, { 74 .type = IIO_ACCEL, 75 .modified = 1, 76 .channel2 = IIO_MOD_Z, 77 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 78 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | 79 BIT(IIO_CHAN_INFO_SCALE) | 80 BIT(IIO_CHAN_INFO_SAMP_FREQ) | 81 BIT(IIO_CHAN_INFO_HYSTERESIS), 82 .scan_index = CHANNEL_SCAN_INDEX_Z, 83 }, 84 IIO_CHAN_SOFT_TIMESTAMP(CHANNEL_SCAN_INDEX_TIMESTAMP) 85 }; 86 87 /* Channel definitions */ 88 static const struct iio_chan_spec gravity_channels[] = { 89 { 90 .type = IIO_GRAVITY, 91 .modified = 1, 92 .channel2 = IIO_MOD_X, 93 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 94 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | 95 BIT(IIO_CHAN_INFO_SCALE) | 96 BIT(IIO_CHAN_INFO_SAMP_FREQ) | 97 BIT(IIO_CHAN_INFO_HYSTERESIS), 98 .scan_index = CHANNEL_SCAN_INDEX_X, 99 }, { 100 .type = IIO_GRAVITY, 101 .modified = 1, 102 .channel2 = IIO_MOD_Y, 103 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 104 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | 105 BIT(IIO_CHAN_INFO_SCALE) | 106 BIT(IIO_CHAN_INFO_SAMP_FREQ) | 107 BIT(IIO_CHAN_INFO_HYSTERESIS), 108 .scan_index = CHANNEL_SCAN_INDEX_Y, 109 }, { 110 .type = IIO_GRAVITY, 111 .modified = 1, 112 .channel2 = IIO_MOD_Z, 113 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 114 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | 115 BIT(IIO_CHAN_INFO_SCALE) | 116 BIT(IIO_CHAN_INFO_SAMP_FREQ) | 117 BIT(IIO_CHAN_INFO_HYSTERESIS), 118 .scan_index = CHANNEL_SCAN_INDEX_Z, 119 }, 120 IIO_CHAN_SOFT_TIMESTAMP(CHANNEL_SCAN_INDEX_TIMESTAMP), 121 }; 122 123 /* Channel read_raw handler */ 124 static int accel_3d_read_raw(struct iio_dev *indio_dev, 125 struct iio_chan_spec const *chan, 126 int *val, int *val2, 127 long mask) 128 { 129 struct accel_3d_state *accel_state = iio_priv(indio_dev); 130 int report_id = -1; 131 u32 address; 132 int ret_type; 133 s32 min; 134 struct hid_sensor_hub_device *hsdev = 135 accel_state->common_attributes.hsdev; 136 137 *val = 0; 138 *val2 = 0; 139 switch (mask) { 140 case IIO_CHAN_INFO_RAW: 141 hid_sensor_power_state(&accel_state->common_attributes, true); 142 report_id = accel_state->accel[chan->scan_index].report_id; 143 min = accel_state->accel[chan->scan_index].logical_minimum; 144 address = accel_3d_addresses[chan->scan_index]; 145 if (report_id >= 0) 146 *val = sensor_hub_input_attr_get_raw_value( 147 accel_state->common_attributes.hsdev, 148 hsdev->usage, address, report_id, 149 SENSOR_HUB_SYNC, 150 min < 0); 151 else { 152 *val = 0; 153 hid_sensor_power_state(&accel_state->common_attributes, 154 false); 155 return -EINVAL; 156 } 157 hid_sensor_power_state(&accel_state->common_attributes, false); 158 ret_type = IIO_VAL_INT; 159 break; 160 case IIO_CHAN_INFO_SCALE: 161 *val = accel_state->scale_pre_decml; 162 *val2 = accel_state->scale_post_decml; 163 ret_type = accel_state->scale_precision; 164 break; 165 case IIO_CHAN_INFO_OFFSET: 166 *val = accel_state->value_offset; 167 ret_type = IIO_VAL_INT; 168 break; 169 case IIO_CHAN_INFO_SAMP_FREQ: 170 ret_type = hid_sensor_read_samp_freq_value( 171 &accel_state->common_attributes, val, val2); 172 break; 173 case IIO_CHAN_INFO_HYSTERESIS: 174 ret_type = hid_sensor_read_raw_hyst_value( 175 &accel_state->common_attributes, val, val2); 176 break; 177 default: 178 ret_type = -EINVAL; 179 break; 180 } 181 182 return ret_type; 183 } 184 185 /* Channel write_raw handler */ 186 static int accel_3d_write_raw(struct iio_dev *indio_dev, 187 struct iio_chan_spec const *chan, 188 int val, 189 int val2, 190 long mask) 191 { 192 struct accel_3d_state *accel_state = iio_priv(indio_dev); 193 int ret = 0; 194 195 switch (mask) { 196 case IIO_CHAN_INFO_SAMP_FREQ: 197 ret = hid_sensor_write_samp_freq_value( 198 &accel_state->common_attributes, val, val2); 199 break; 200 case IIO_CHAN_INFO_HYSTERESIS: 201 ret = hid_sensor_write_raw_hyst_value( 202 &accel_state->common_attributes, val, val2); 203 break; 204 default: 205 ret = -EINVAL; 206 } 207 208 return ret; 209 } 210 211 static const struct iio_info accel_3d_info = { 212 .read_raw = &accel_3d_read_raw, 213 .write_raw = &accel_3d_write_raw, 214 }; 215 216 /* Function to push data to buffer */ 217 static void hid_sensor_push_data(struct iio_dev *indio_dev, void *data, 218 int len, int64_t timestamp) 219 { 220 dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n"); 221 iio_push_to_buffers_with_ts(indio_dev, data, len, timestamp); 222 } 223 224 /* Callback handler to send event after all samples are received and captured */ 225 static int accel_3d_proc_event(struct hid_sensor_hub_device *hsdev, 226 unsigned usage_id, 227 void *priv) 228 { 229 struct iio_dev *indio_dev = platform_get_drvdata(priv); 230 struct accel_3d_state *accel_state = iio_priv(indio_dev); 231 232 dev_dbg(&indio_dev->dev, "accel_3d_proc_event\n"); 233 if (atomic_read(&accel_state->common_attributes.data_ready)) { 234 if (!accel_state->timestamp) 235 accel_state->timestamp = iio_get_time_ns(indio_dev); 236 237 hid_sensor_push_data(indio_dev, 238 &accel_state->scan, 239 sizeof(accel_state->scan), 240 accel_state->timestamp); 241 242 accel_state->timestamp = 0; 243 } 244 245 return 0; 246 } 247 248 /* Capture samples in local storage */ 249 static int accel_3d_capture_sample(struct hid_sensor_hub_device *hsdev, 250 unsigned usage_id, 251 size_t raw_len, char *raw_data, 252 void *priv) 253 { 254 struct iio_dev *indio_dev = platform_get_drvdata(priv); 255 struct accel_3d_state *accel_state = iio_priv(indio_dev); 256 int offset; 257 int ret = -EINVAL; 258 259 switch (usage_id) { 260 case HID_USAGE_SENSOR_ACCEL_X_AXIS: 261 case HID_USAGE_SENSOR_ACCEL_Y_AXIS: 262 case HID_USAGE_SENSOR_ACCEL_Z_AXIS: 263 offset = usage_id - HID_USAGE_SENSOR_ACCEL_X_AXIS; 264 accel_state->scan.accel_val[CHANNEL_SCAN_INDEX_X + offset] = 265 *(u32 *)raw_data; 266 ret = 0; 267 break; 268 case HID_USAGE_SENSOR_TIME_TIMESTAMP: 269 accel_state->timestamp = 270 hid_sensor_convert_timestamp( 271 &accel_state->common_attributes, 272 *(int64_t *)raw_data); 273 ret = 0; 274 break; 275 default: 276 break; 277 } 278 279 return ret; 280 } 281 282 /* Parse report which is specific to an usage id*/ 283 static int accel_3d_parse_report(struct platform_device *pdev, 284 struct hid_sensor_hub_device *hsdev, 285 struct iio_chan_spec *channels, 286 unsigned usage_id, 287 struct accel_3d_state *st) 288 { 289 int ret; 290 291 for (unsigned int ch = CHANNEL_SCAN_INDEX_X; ch <= CHANNEL_SCAN_INDEX_Z; ch++) { 292 ret = sensor_hub_input_get_attribute_info(hsdev, 293 HID_INPUT_REPORT, 294 usage_id, 295 HID_USAGE_SENSOR_ACCEL_X_AXIS + ch, 296 &st->accel[ch]); 297 if (ret < 0) 298 break; 299 channels[ch].scan_type = (struct iio_scan_type) { 300 .format = 's', 301 .realbits = BYTES_TO_BITS(st->accel[ch].size), 302 .storagebits = BITS_PER_TYPE(u32), 303 }; 304 } 305 dev_dbg(&pdev->dev, "accel_3d %x:%x, %x:%x, %x:%x\n", 306 st->accel[0].index, 307 st->accel[0].report_id, 308 st->accel[1].index, st->accel[1].report_id, 309 st->accel[2].index, st->accel[2].report_id); 310 311 st->scale_precision = hid_sensor_format_scale( 312 hsdev->usage, 313 &st->accel[CHANNEL_SCAN_INDEX_X], 314 &st->scale_pre_decml, &st->scale_post_decml); 315 316 return ret; 317 } 318 319 /* Function to initialize the processing for usage id */ 320 static int hid_accel_3d_probe(struct platform_device *pdev) 321 { 322 struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev); 323 int ret = 0; 324 const char *name; 325 struct iio_dev *indio_dev; 326 struct accel_3d_state *accel_state; 327 const struct iio_chan_spec *channel_spec; 328 int channel_size; 329 330 indio_dev = devm_iio_device_alloc(&pdev->dev, 331 sizeof(struct accel_3d_state)); 332 if (indio_dev == NULL) 333 return -ENOMEM; 334 335 platform_set_drvdata(pdev, indio_dev); 336 337 accel_state = iio_priv(indio_dev); 338 accel_state->common_attributes.hsdev = hsdev; 339 accel_state->common_attributes.pdev = pdev; 340 341 if (hsdev->usage == HID_USAGE_SENSOR_ACCEL_3D) { 342 name = "accel_3d"; 343 channel_spec = accel_3d_channels; 344 channel_size = sizeof(accel_3d_channels); 345 indio_dev->num_channels = ARRAY_SIZE(accel_3d_channels); 346 } else { 347 name = "gravity"; 348 channel_spec = gravity_channels; 349 channel_size = sizeof(gravity_channels); 350 indio_dev->num_channels = ARRAY_SIZE(gravity_channels); 351 } 352 ret = hid_sensor_parse_common_attributes(hsdev, 353 hsdev->usage, 354 &accel_state->common_attributes, 355 accel_3d_sensitivity_addresses, 356 ARRAY_SIZE(accel_3d_sensitivity_addresses)); 357 if (ret) { 358 dev_err(&pdev->dev, "failed to setup common attributes\n"); 359 return ret; 360 } 361 indio_dev->channels = devm_kmemdup(&pdev->dev, channel_spec, 362 channel_size, GFP_KERNEL); 363 364 if (!indio_dev->channels) { 365 dev_err(&pdev->dev, "failed to duplicate channels\n"); 366 return -ENOMEM; 367 } 368 ret = accel_3d_parse_report(pdev, hsdev, 369 (struct iio_chan_spec *)indio_dev->channels, 370 hsdev->usage, accel_state); 371 if (ret) { 372 dev_err(&pdev->dev, "failed to setup attributes\n"); 373 return ret; 374 } 375 376 indio_dev->info = &accel_3d_info; 377 indio_dev->name = name; 378 indio_dev->modes = INDIO_DIRECT_MODE; 379 380 atomic_set(&accel_state->common_attributes.data_ready, 0); 381 382 ret = hid_sensor_setup_trigger(indio_dev, name, 383 &accel_state->common_attributes); 384 if (ret < 0) { 385 dev_err(&pdev->dev, "trigger setup failed\n"); 386 return ret; 387 } 388 389 ret = iio_device_register(indio_dev); 390 if (ret) { 391 dev_err(&pdev->dev, "device register failed\n"); 392 goto error_remove_trigger; 393 } 394 395 accel_state->callbacks.send_event = accel_3d_proc_event; 396 accel_state->callbacks.capture_sample = accel_3d_capture_sample; 397 accel_state->callbacks.pdev = pdev; 398 ret = sensor_hub_register_callback(hsdev, hsdev->usage, 399 &accel_state->callbacks); 400 if (ret < 0) { 401 dev_err(&pdev->dev, "callback reg failed\n"); 402 goto error_iio_unreg; 403 } 404 405 return ret; 406 407 error_iio_unreg: 408 iio_device_unregister(indio_dev); 409 error_remove_trigger: 410 hid_sensor_remove_trigger(indio_dev, &accel_state->common_attributes); 411 return ret; 412 } 413 414 /* Function to deinitialize the processing for usage id */ 415 static void hid_accel_3d_remove(struct platform_device *pdev) 416 { 417 struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev); 418 struct iio_dev *indio_dev = platform_get_drvdata(pdev); 419 struct accel_3d_state *accel_state = iio_priv(indio_dev); 420 421 sensor_hub_remove_callback(hsdev, hsdev->usage); 422 iio_device_unregister(indio_dev); 423 hid_sensor_remove_trigger(indio_dev, &accel_state->common_attributes); 424 } 425 426 static const struct platform_device_id hid_accel_3d_ids[] = { 427 { 428 /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ 429 .name = "HID-SENSOR-200073", 430 }, 431 { /* gravity sensor */ 432 .name = "HID-SENSOR-20007b", 433 }, 434 { } 435 }; 436 MODULE_DEVICE_TABLE(platform, hid_accel_3d_ids); 437 438 static struct platform_driver hid_accel_3d_platform_driver = { 439 .id_table = hid_accel_3d_ids, 440 .driver = { 441 .name = KBUILD_MODNAME, 442 .pm = &hid_sensor_pm_ops, 443 }, 444 .probe = hid_accel_3d_probe, 445 .remove = hid_accel_3d_remove, 446 }; 447 module_platform_driver(hid_accel_3d_platform_driver); 448 449 MODULE_DESCRIPTION("HID Sensor Accel 3D"); 450 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>"); 451 MODULE_LICENSE("GPL"); 452 MODULE_IMPORT_NS("IIO_HID"); 453