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