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