1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * HID Sensors Driver 4 * Copyright (c) 2012, 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/kernel.h> 12 #include <linux/slab.h> 13 #include <linux/time.h> 14 15 #include <linux/hid-sensor-hub.h> 16 #include <linux/iio/iio.h> 17 #include <linux/iio/sysfs.h> 18 19 #define HZ_PER_MHZ 1000000L 20 21 static struct { 22 u32 usage_id; 23 int unit; /* 0 for default others from HID sensor spec */ 24 int scale_val0; /* scale, whole number */ 25 int scale_val1; /* scale, fraction in nanos */ 26 } unit_conversion[] = { 27 {HID_USAGE_SENSOR_ACCEL_3D, 0, 9, 806650000}, 28 {HID_USAGE_SENSOR_ACCEL_3D, 29 HID_USAGE_SENSOR_UNITS_METERS_PER_SEC_SQRD, 1, 0}, 30 {HID_USAGE_SENSOR_ACCEL_3D, 31 HID_USAGE_SENSOR_UNITS_G, 9, 806650000}, 32 33 {HID_USAGE_SENSOR_GRAVITY_VECTOR, 0, 9, 806650000}, 34 {HID_USAGE_SENSOR_GRAVITY_VECTOR, 35 HID_USAGE_SENSOR_UNITS_METERS_PER_SEC_SQRD, 1, 0}, 36 {HID_USAGE_SENSOR_GRAVITY_VECTOR, 37 HID_USAGE_SENSOR_UNITS_G, 9, 806650000}, 38 39 {HID_USAGE_SENSOR_GYRO_3D, 0, 0, 17453293}, 40 {HID_USAGE_SENSOR_GYRO_3D, 41 HID_USAGE_SENSOR_UNITS_RADIANS_PER_SECOND, 1, 0}, 42 {HID_USAGE_SENSOR_GYRO_3D, 43 HID_USAGE_SENSOR_UNITS_DEGREES_PER_SECOND, 0, 17453293}, 44 45 {HID_USAGE_SENSOR_COMPASS_3D, 0, 0, 1000000}, 46 {HID_USAGE_SENSOR_COMPASS_3D, HID_USAGE_SENSOR_UNITS_GAUSS, 1, 0}, 47 48 {HID_USAGE_SENSOR_INCLINOMETER_3D, 0, 0, 17453293}, 49 {HID_USAGE_SENSOR_INCLINOMETER_3D, 50 HID_USAGE_SENSOR_UNITS_DEGREES, 0, 17453293}, 51 {HID_USAGE_SENSOR_INCLINOMETER_3D, 52 HID_USAGE_SENSOR_UNITS_RADIANS, 1, 0}, 53 54 {HID_USAGE_SENSOR_ALS, 0, 1, 0}, 55 {HID_USAGE_SENSOR_ALS, HID_USAGE_SENSOR_UNITS_LUX, 1, 0}, 56 57 {HID_USAGE_SENSOR_PRESSURE, 0, 100, 0}, 58 {HID_USAGE_SENSOR_PRESSURE, HID_USAGE_SENSOR_UNITS_PASCAL, 0, 1000000}, 59 60 {HID_USAGE_SENSOR_TIME_TIMESTAMP, 0, 1000000000, 0}, 61 {HID_USAGE_SENSOR_TIME_TIMESTAMP, HID_USAGE_SENSOR_UNITS_MILLISECOND, 62 1000000, 0}, 63 64 {HID_USAGE_SENSOR_DEVICE_ORIENTATION, 0, 1, 0}, 65 66 {HID_USAGE_SENSOR_RELATIVE_ORIENTATION, 0, 1, 0}, 67 68 {HID_USAGE_SENSOR_GEOMAGNETIC_ORIENTATION, 0, 1, 0}, 69 70 {HID_USAGE_SENSOR_TEMPERATURE, 0, 1000, 0}, 71 {HID_USAGE_SENSOR_TEMPERATURE, HID_USAGE_SENSOR_UNITS_DEGREES, 1000, 0}, 72 73 {HID_USAGE_SENSOR_HUMIDITY, 0, 1000, 0}, 74 {HID_USAGE_SENSOR_HINGE, 0, 0, 17453293}, 75 {HID_USAGE_SENSOR_HINGE, HID_USAGE_SENSOR_UNITS_DEGREES, 0, 17453293}, 76 }; 77 78 static void simple_div(int dividend, int divisor, int *whole, 79 int *micro_frac) 80 { 81 int rem; 82 int exp = 0; 83 84 *micro_frac = 0; 85 if (divisor == 0) { 86 *whole = 0; 87 return; 88 } 89 *whole = dividend/divisor; 90 rem = dividend % divisor; 91 if (rem) { 92 while (rem <= divisor) { 93 rem *= 10; 94 exp++; 95 } 96 *micro_frac = (rem / divisor) * int_pow(10, 6 - exp); 97 } 98 } 99 100 static void split_micro_fraction(unsigned int no, int exp, int *val1, int *val2) 101 { 102 int divisor = int_pow(10, exp); 103 104 *val1 = no / divisor; 105 *val2 = no % divisor * int_pow(10, 6 - exp); 106 } 107 108 /* 109 VTF format uses exponent and variable size format. 110 For example if the size is 2 bytes 111 0x0067 with VTF16E14 format -> +1.03 112 To convert just change to 0x67 to decimal and use two decimal as E14 stands 113 for 10^-2. 114 Negative numbers are 2's complement 115 */ 116 static void convert_from_vtf_format(u32 value, int size, int exp, 117 int *val1, int *val2) 118 { 119 int sign = 1; 120 121 if (value & BIT(size*8 - 1)) { 122 value = ((1LL << (size * 8)) - value); 123 sign = -1; 124 } 125 exp = hid_sensor_convert_exponent(exp); 126 if (exp >= 0) { 127 *val1 = sign * value * int_pow(10, exp); 128 *val2 = 0; 129 } else { 130 split_micro_fraction(value, -exp, val1, val2); 131 if (*val1) 132 *val1 = sign * (*val1); 133 else 134 *val2 = sign * (*val2); 135 } 136 } 137 138 static u32 convert_to_vtf_format(int size, int exp, int val1, int val2) 139 { 140 int divisor; 141 u32 value; 142 int sign = 1; 143 144 if (val1 < 0 || val2 < 0) 145 sign = -1; 146 exp = hid_sensor_convert_exponent(exp); 147 if (exp < 0) { 148 divisor = int_pow(10, 6 + exp); 149 value = abs(val1) * int_pow(10, -exp); 150 value += abs(val2) / divisor; 151 } else { 152 divisor = int_pow(10, exp); 153 value = abs(val1) / divisor; 154 } 155 if (sign < 0) 156 value = ((1LL << (size * 8)) - value); 157 158 return value; 159 } 160 161 s32 hid_sensor_read_poll_value(struct hid_sensor_common *st) 162 { 163 s32 value = 0; 164 int ret; 165 166 ret = sensor_hub_get_feature(st->hsdev, 167 st->poll.report_id, 168 st->poll.index, sizeof(value), &value); 169 170 if (ret < 0 || value < 0) { 171 return -EINVAL; 172 } else { 173 if (st->poll.units == HID_USAGE_SENSOR_UNITS_SECOND) 174 value = value * 1000; 175 } 176 177 return value; 178 } 179 EXPORT_SYMBOL(hid_sensor_read_poll_value); 180 181 int hid_sensor_read_samp_freq_value(struct hid_sensor_common *st, 182 int *val1, int *val2) 183 { 184 s32 value; 185 int ret; 186 187 ret = sensor_hub_get_feature(st->hsdev, 188 st->poll.report_id, 189 st->poll.index, sizeof(value), &value); 190 if (ret < 0 || value < 0) { 191 *val1 = *val2 = 0; 192 return -EINVAL; 193 } else { 194 if (st->poll.units == HID_USAGE_SENSOR_UNITS_MILLISECOND) 195 simple_div(1000, value, val1, val2); 196 else if (st->poll.units == HID_USAGE_SENSOR_UNITS_SECOND) 197 simple_div(1, value, val1, val2); 198 else { 199 *val1 = *val2 = 0; 200 return -EINVAL; 201 } 202 } 203 204 return IIO_VAL_INT_PLUS_MICRO; 205 } 206 EXPORT_SYMBOL(hid_sensor_read_samp_freq_value); 207 208 int hid_sensor_write_samp_freq_value(struct hid_sensor_common *st, 209 int val1, int val2) 210 { 211 s32 value; 212 int ret; 213 214 if (val1 < 0 || val2 < 0) 215 return -EINVAL; 216 217 value = val1 * HZ_PER_MHZ + val2; 218 if (value) { 219 if (st->poll.units == HID_USAGE_SENSOR_UNITS_MILLISECOND) 220 value = NSEC_PER_SEC / value; 221 else if (st->poll.units == HID_USAGE_SENSOR_UNITS_SECOND) 222 value = USEC_PER_SEC / value; 223 else 224 value = 0; 225 } 226 ret = sensor_hub_set_feature(st->hsdev, st->poll.report_id, 227 st->poll.index, sizeof(value), &value); 228 if (ret < 0 || value < 0) 229 return -EINVAL; 230 231 ret = sensor_hub_get_feature(st->hsdev, 232 st->poll.report_id, 233 st->poll.index, sizeof(value), &value); 234 if (ret < 0 || value < 0) 235 return -EINVAL; 236 237 st->poll_interval = value; 238 239 return 0; 240 } 241 EXPORT_SYMBOL(hid_sensor_write_samp_freq_value); 242 243 int hid_sensor_read_raw_hyst_value(struct hid_sensor_common *st, 244 int *val1, int *val2) 245 { 246 s32 value; 247 int ret; 248 249 ret = sensor_hub_get_feature(st->hsdev, 250 st->sensitivity.report_id, 251 st->sensitivity.index, sizeof(value), 252 &value); 253 if (ret < 0 || value < 0) { 254 *val1 = *val2 = 0; 255 return -EINVAL; 256 } else { 257 convert_from_vtf_format(value, st->sensitivity.size, 258 st->sensitivity.unit_expo, 259 val1, val2); 260 } 261 262 return IIO_VAL_INT_PLUS_MICRO; 263 } 264 EXPORT_SYMBOL(hid_sensor_read_raw_hyst_value); 265 266 int hid_sensor_write_raw_hyst_value(struct hid_sensor_common *st, 267 int val1, int val2) 268 { 269 s32 value; 270 int ret; 271 272 if (val1 < 0 || val2 < 0) 273 return -EINVAL; 274 275 value = convert_to_vtf_format(st->sensitivity.size, 276 st->sensitivity.unit_expo, 277 val1, val2); 278 ret = sensor_hub_set_feature(st->hsdev, st->sensitivity.report_id, 279 st->sensitivity.index, sizeof(value), 280 &value); 281 if (ret < 0 || value < 0) 282 return -EINVAL; 283 284 ret = sensor_hub_get_feature(st->hsdev, 285 st->sensitivity.report_id, 286 st->sensitivity.index, sizeof(value), 287 &value); 288 if (ret < 0 || value < 0) 289 return -EINVAL; 290 291 st->raw_hystersis = value; 292 293 return 0; 294 } 295 EXPORT_SYMBOL(hid_sensor_write_raw_hyst_value); 296 297 /* 298 * This fuction applies the unit exponent to the scale. 299 * For example: 300 * 9.806650000 ->exp:2-> val0[980]val1[665000000] 301 * 9.000806000 ->exp:2-> val0[900]val1[80600000] 302 * 0.174535293 ->exp:2-> val0[17]val1[453529300] 303 * 1.001745329 ->exp:0-> val0[1]val1[1745329] 304 * 1.001745329 ->exp:2-> val0[100]val1[174532900] 305 * 1.001745329 ->exp:4-> val0[10017]val1[453290000] 306 * 9.806650000 ->exp:-2-> val0[0]val1[98066500] 307 */ 308 static void adjust_exponent_nano(int *val0, int *val1, int scale0, 309 int scale1, int exp) 310 { 311 int divisor; 312 int i; 313 int x; 314 int res; 315 int rem; 316 317 if (exp > 0) { 318 *val0 = scale0 * int_pow(10, exp); 319 res = 0; 320 if (exp > 9) { 321 *val1 = 0; 322 return; 323 } 324 for (i = 0; i < exp; ++i) { 325 divisor = int_pow(10, 8 - i); 326 x = scale1 / divisor; 327 res += int_pow(10, exp - 1 - i) * x; 328 scale1 = scale1 % divisor; 329 } 330 *val0 += res; 331 *val1 = scale1 * int_pow(10, exp); 332 } else if (exp < 0) { 333 exp = abs(exp); 334 if (exp > 9) { 335 *val0 = *val1 = 0; 336 return; 337 } 338 divisor = int_pow(10, exp); 339 *val0 = scale0 / divisor; 340 rem = scale0 % divisor; 341 res = 0; 342 for (i = 0; i < (9 - exp); ++i) { 343 divisor = int_pow(10, 8 - i); 344 x = scale1 / divisor; 345 res += int_pow(10, 8 - exp - i) * x; 346 scale1 = scale1 % divisor; 347 } 348 *val1 = rem * int_pow(10, 9 - exp) + res; 349 } else { 350 *val0 = scale0; 351 *val1 = scale1; 352 } 353 } 354 355 int hid_sensor_format_scale(u32 usage_id, 356 struct hid_sensor_hub_attribute_info *attr_info, 357 int *val0, int *val1) 358 { 359 int i; 360 int exp; 361 362 *val0 = 1; 363 *val1 = 0; 364 365 for (i = 0; i < ARRAY_SIZE(unit_conversion); ++i) { 366 if (unit_conversion[i].usage_id == usage_id && 367 unit_conversion[i].unit == attr_info->units) { 368 exp = hid_sensor_convert_exponent( 369 attr_info->unit_expo); 370 adjust_exponent_nano(val0, val1, 371 unit_conversion[i].scale_val0, 372 unit_conversion[i].scale_val1, exp); 373 break; 374 } 375 } 376 377 return IIO_VAL_INT_PLUS_NANO; 378 } 379 EXPORT_SYMBOL(hid_sensor_format_scale); 380 381 int64_t hid_sensor_convert_timestamp(struct hid_sensor_common *st, 382 int64_t raw_value) 383 { 384 return st->timestamp_ns_scale * raw_value; 385 } 386 EXPORT_SYMBOL(hid_sensor_convert_timestamp); 387 388 static 389 int hid_sensor_get_reporting_interval(struct hid_sensor_hub_device *hsdev, 390 u32 usage_id, 391 struct hid_sensor_common *st) 392 { 393 sensor_hub_input_get_attribute_info(hsdev, 394 HID_FEATURE_REPORT, usage_id, 395 HID_USAGE_SENSOR_PROP_REPORT_INTERVAL, 396 &st->poll); 397 /* Default unit of measure is milliseconds */ 398 if (st->poll.units == 0) 399 st->poll.units = HID_USAGE_SENSOR_UNITS_MILLISECOND; 400 401 st->poll_interval = -1; 402 403 return 0; 404 405 } 406 407 static void hid_sensor_get_report_latency_info(struct hid_sensor_hub_device *hsdev, 408 u32 usage_id, 409 struct hid_sensor_common *st) 410 { 411 sensor_hub_input_get_attribute_info(hsdev, HID_FEATURE_REPORT, 412 usage_id, 413 HID_USAGE_SENSOR_PROP_REPORT_LATENCY, 414 &st->report_latency); 415 416 hid_dbg(hsdev->hdev, "Report latency attributes: %x:%x\n", 417 st->report_latency.index, st->report_latency.report_id); 418 } 419 420 int hid_sensor_get_report_latency(struct hid_sensor_common *st) 421 { 422 int ret; 423 int value; 424 425 ret = sensor_hub_get_feature(st->hsdev, st->report_latency.report_id, 426 st->report_latency.index, sizeof(value), 427 &value); 428 if (ret < 0) 429 return ret; 430 431 return value; 432 } 433 EXPORT_SYMBOL(hid_sensor_get_report_latency); 434 435 int hid_sensor_set_report_latency(struct hid_sensor_common *st, int latency_ms) 436 { 437 return sensor_hub_set_feature(st->hsdev, st->report_latency.report_id, 438 st->report_latency.index, 439 sizeof(latency_ms), &latency_ms); 440 } 441 EXPORT_SYMBOL(hid_sensor_set_report_latency); 442 443 bool hid_sensor_batch_mode_supported(struct hid_sensor_common *st) 444 { 445 return st->report_latency.index > 0 && st->report_latency.report_id > 0; 446 } 447 EXPORT_SYMBOL(hid_sensor_batch_mode_supported); 448 449 int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev, 450 u32 usage_id, 451 struct hid_sensor_common *st) 452 { 453 454 struct hid_sensor_hub_attribute_info timestamp; 455 s32 value; 456 int ret; 457 458 hid_sensor_get_reporting_interval(hsdev, usage_id, st); 459 460 sensor_hub_input_get_attribute_info(hsdev, 461 HID_FEATURE_REPORT, usage_id, 462 HID_USAGE_SENSOR_PROP_REPORT_STATE, 463 &st->report_state); 464 465 sensor_hub_input_get_attribute_info(hsdev, 466 HID_FEATURE_REPORT, usage_id, 467 HID_USAGE_SENSOR_PROY_POWER_STATE, 468 &st->power_state); 469 470 st->power_state.logical_minimum = 1; 471 st->report_state.logical_minimum = 1; 472 473 sensor_hub_input_get_attribute_info(hsdev, 474 HID_FEATURE_REPORT, usage_id, 475 HID_USAGE_SENSOR_PROP_SENSITIVITY_ABS, 476 &st->sensitivity); 477 478 st->raw_hystersis = -1; 479 480 sensor_hub_input_get_attribute_info(hsdev, 481 HID_INPUT_REPORT, usage_id, 482 HID_USAGE_SENSOR_TIME_TIMESTAMP, 483 ×tamp); 484 if (timestamp.index >= 0 && timestamp.report_id) { 485 int val0, val1; 486 487 hid_sensor_format_scale(HID_USAGE_SENSOR_TIME_TIMESTAMP, 488 ×tamp, &val0, &val1); 489 st->timestamp_ns_scale = val0; 490 } else 491 st->timestamp_ns_scale = 1000000000; 492 493 hid_sensor_get_report_latency_info(hsdev, usage_id, st); 494 495 hid_dbg(hsdev->hdev, "common attributes: %x:%x, %x:%x, %x:%x %x:%x %x:%x\n", 496 st->poll.index, st->poll.report_id, 497 st->report_state.index, st->report_state.report_id, 498 st->power_state.index, st->power_state.report_id, 499 st->sensitivity.index, st->sensitivity.report_id, 500 timestamp.index, timestamp.report_id); 501 502 ret = sensor_hub_get_feature(hsdev, 503 st->power_state.report_id, 504 st->power_state.index, sizeof(value), &value); 505 if (ret < 0) 506 return ret; 507 if (value < 0) 508 return -EINVAL; 509 510 return 0; 511 } 512 EXPORT_SYMBOL(hid_sensor_parse_common_attributes); 513 514 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>"); 515 MODULE_DESCRIPTION("HID Sensor common attribute processing"); 516 MODULE_LICENSE("GPL"); 517