1 /* 2 * HID Sensors Driver 3 * Copyright (c) 2012, Intel Corporation. 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms and conditions of the GNU General Public License, 7 * version 2, as published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 * 14 * You should have received a copy of the GNU General Public License along with 15 * this program; if not, write to the Free Software Foundation, Inc., 16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 17 * 18 */ 19 #include <linux/device.h> 20 #include <linux/platform_device.h> 21 #include <linux/module.h> 22 #include <linux/interrupt.h> 23 #include <linux/irq.h> 24 #include <linux/slab.h> 25 #include <linux/delay.h> 26 #include <linux/hid-sensor-hub.h> 27 #include <linux/iio/iio.h> 28 #include <linux/iio/sysfs.h> 29 #include <linux/iio/buffer.h> 30 #include <linux/iio/trigger_consumer.h> 31 #include <linux/iio/triggered_buffer.h> 32 #include "../common/hid-sensors/hid-sensor-trigger.h" 33 34 enum magn_3d_channel { 35 CHANNEL_SCAN_INDEX_X, 36 CHANNEL_SCAN_INDEX_Y, 37 CHANNEL_SCAN_INDEX_Z, 38 CHANNEL_SCAN_INDEX_NORTH_MAGN_TILT_COMP, 39 CHANNEL_SCAN_INDEX_NORTH_TRUE_TILT_COMP, 40 CHANNEL_SCAN_INDEX_NORTH_MAGN, 41 CHANNEL_SCAN_INDEX_NORTH_TRUE, 42 MAGN_3D_CHANNEL_MAX, 43 }; 44 45 struct common_attributes { 46 int scale_pre_decml; 47 int scale_post_decml; 48 int scale_precision; 49 int value_offset; 50 }; 51 52 struct magn_3d_state { 53 struct hid_sensor_hub_callbacks callbacks; 54 struct hid_sensor_common magn_flux_attributes; 55 struct hid_sensor_common rot_attributes; 56 struct hid_sensor_hub_attribute_info magn[MAGN_3D_CHANNEL_MAX]; 57 58 /* dynamically sized array to hold sensor values */ 59 u32 *iio_vals; 60 /* array of pointers to sensor value */ 61 u32 *magn_val_addr[MAGN_3D_CHANNEL_MAX]; 62 63 struct common_attributes magn_flux_attr; 64 struct common_attributes rot_attr; 65 }; 66 67 static const u32 magn_3d_addresses[MAGN_3D_CHANNEL_MAX] = { 68 HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS, 69 HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Y_AXIS, 70 HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Z_AXIS, 71 HID_USAGE_SENSOR_ORIENT_COMP_MAGN_NORTH, 72 HID_USAGE_SENSOR_ORIENT_COMP_TRUE_NORTH, 73 HID_USAGE_SENSOR_ORIENT_MAGN_NORTH, 74 HID_USAGE_SENSOR_ORIENT_TRUE_NORTH, 75 }; 76 77 /* Channel definitions */ 78 static const struct iio_chan_spec magn_3d_channels[] = { 79 { 80 .type = IIO_MAGN, 81 .modified = 1, 82 .channel2 = IIO_MOD_X, 83 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 84 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | 85 BIT(IIO_CHAN_INFO_SCALE) | 86 BIT(IIO_CHAN_INFO_SAMP_FREQ) | 87 BIT(IIO_CHAN_INFO_HYSTERESIS), 88 }, { 89 .type = IIO_MAGN, 90 .modified = 1, 91 .channel2 = IIO_MOD_Y, 92 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 93 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | 94 BIT(IIO_CHAN_INFO_SCALE) | 95 BIT(IIO_CHAN_INFO_SAMP_FREQ) | 96 BIT(IIO_CHAN_INFO_HYSTERESIS), 97 }, { 98 .type = IIO_MAGN, 99 .modified = 1, 100 .channel2 = IIO_MOD_Z, 101 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 102 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | 103 BIT(IIO_CHAN_INFO_SCALE) | 104 BIT(IIO_CHAN_INFO_SAMP_FREQ) | 105 BIT(IIO_CHAN_INFO_HYSTERESIS), 106 }, { 107 .type = IIO_ROT, 108 .modified = 1, 109 .channel2 = IIO_MOD_NORTH_MAGN_TILT_COMP, 110 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 111 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | 112 BIT(IIO_CHAN_INFO_SCALE) | 113 BIT(IIO_CHAN_INFO_SAMP_FREQ) | 114 BIT(IIO_CHAN_INFO_HYSTERESIS), 115 }, { 116 .type = IIO_ROT, 117 .modified = 1, 118 .channel2 = IIO_MOD_NORTH_TRUE_TILT_COMP, 119 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 120 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | 121 BIT(IIO_CHAN_INFO_SCALE) | 122 BIT(IIO_CHAN_INFO_SAMP_FREQ) | 123 BIT(IIO_CHAN_INFO_HYSTERESIS), 124 }, { 125 .type = IIO_ROT, 126 .modified = 1, 127 .channel2 = IIO_MOD_NORTH_MAGN, 128 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 129 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | 130 BIT(IIO_CHAN_INFO_SCALE) | 131 BIT(IIO_CHAN_INFO_SAMP_FREQ) | 132 BIT(IIO_CHAN_INFO_HYSTERESIS), 133 }, { 134 .type = IIO_ROT, 135 .modified = 1, 136 .channel2 = IIO_MOD_NORTH_TRUE, 137 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 138 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | 139 BIT(IIO_CHAN_INFO_SCALE) | 140 BIT(IIO_CHAN_INFO_SAMP_FREQ) | 141 BIT(IIO_CHAN_INFO_HYSTERESIS), 142 } 143 }; 144 145 /* Adjust channel real bits based on report descriptor */ 146 static void magn_3d_adjust_channel_bit_mask(struct iio_chan_spec *channels, 147 int channel, int size) 148 { 149 channels[channel].scan_type.sign = 's'; 150 /* Real storage bits will change based on the report desc. */ 151 channels[channel].scan_type.realbits = size * 8; 152 /* Maximum size of a sample to capture is u32 */ 153 channels[channel].scan_type.storagebits = sizeof(u32) * 8; 154 } 155 156 /* Channel read_raw handler */ 157 static int magn_3d_read_raw(struct iio_dev *indio_dev, 158 struct iio_chan_spec const *chan, 159 int *val, int *val2, 160 long mask) 161 { 162 struct magn_3d_state *magn_state = iio_priv(indio_dev); 163 int report_id = -1; 164 u32 address; 165 int ret_type; 166 s32 min; 167 168 *val = 0; 169 *val2 = 0; 170 switch (mask) { 171 case IIO_CHAN_INFO_RAW: 172 hid_sensor_power_state(&magn_state->magn_flux_attributes, true); 173 report_id = magn_state->magn[chan->address].report_id; 174 min = magn_state->magn[chan->address].logical_minimum; 175 address = magn_3d_addresses[chan->address]; 176 if (report_id >= 0) 177 *val = sensor_hub_input_attr_get_raw_value( 178 magn_state->magn_flux_attributes.hsdev, 179 HID_USAGE_SENSOR_COMPASS_3D, address, 180 report_id, 181 SENSOR_HUB_SYNC, 182 min < 0); 183 else { 184 *val = 0; 185 hid_sensor_power_state( 186 &magn_state->magn_flux_attributes, 187 false); 188 return -EINVAL; 189 } 190 hid_sensor_power_state(&magn_state->magn_flux_attributes, 191 false); 192 ret_type = IIO_VAL_INT; 193 break; 194 case IIO_CHAN_INFO_SCALE: 195 switch (chan->type) { 196 case IIO_MAGN: 197 *val = magn_state->magn_flux_attr.scale_pre_decml; 198 *val2 = magn_state->magn_flux_attr.scale_post_decml; 199 ret_type = magn_state->magn_flux_attr.scale_precision; 200 break; 201 case IIO_ROT: 202 *val = magn_state->rot_attr.scale_pre_decml; 203 *val2 = magn_state->rot_attr.scale_post_decml; 204 ret_type = magn_state->rot_attr.scale_precision; 205 break; 206 default: 207 ret_type = -EINVAL; 208 } 209 break; 210 case IIO_CHAN_INFO_OFFSET: 211 switch (chan->type) { 212 case IIO_MAGN: 213 *val = magn_state->magn_flux_attr.value_offset; 214 ret_type = IIO_VAL_INT; 215 break; 216 case IIO_ROT: 217 *val = magn_state->rot_attr.value_offset; 218 ret_type = IIO_VAL_INT; 219 break; 220 default: 221 ret_type = -EINVAL; 222 } 223 break; 224 case IIO_CHAN_INFO_SAMP_FREQ: 225 ret_type = hid_sensor_read_samp_freq_value( 226 &magn_state->magn_flux_attributes, val, val2); 227 break; 228 case IIO_CHAN_INFO_HYSTERESIS: 229 switch (chan->type) { 230 case IIO_MAGN: 231 ret_type = hid_sensor_read_raw_hyst_value( 232 &magn_state->magn_flux_attributes, val, val2); 233 break; 234 case IIO_ROT: 235 ret_type = hid_sensor_read_raw_hyst_value( 236 &magn_state->rot_attributes, val, val2); 237 break; 238 default: 239 ret_type = -EINVAL; 240 } 241 break; 242 default: 243 ret_type = -EINVAL; 244 break; 245 } 246 247 return ret_type; 248 } 249 250 /* Channel write_raw handler */ 251 static int magn_3d_write_raw(struct iio_dev *indio_dev, 252 struct iio_chan_spec const *chan, 253 int val, 254 int val2, 255 long mask) 256 { 257 struct magn_3d_state *magn_state = iio_priv(indio_dev); 258 int ret = 0; 259 260 switch (mask) { 261 case IIO_CHAN_INFO_SAMP_FREQ: 262 ret = hid_sensor_write_samp_freq_value( 263 &magn_state->magn_flux_attributes, val, val2); 264 break; 265 case IIO_CHAN_INFO_HYSTERESIS: 266 switch (chan->type) { 267 case IIO_MAGN: 268 ret = hid_sensor_write_raw_hyst_value( 269 &magn_state->magn_flux_attributes, val, val2); 270 break; 271 case IIO_ROT: 272 ret = hid_sensor_write_raw_hyst_value( 273 &magn_state->rot_attributes, val, val2); 274 break; 275 default: 276 ret = -EINVAL; 277 } 278 break; 279 default: 280 ret = -EINVAL; 281 } 282 283 return ret; 284 } 285 286 static const struct iio_info magn_3d_info = { 287 .read_raw = &magn_3d_read_raw, 288 .write_raw = &magn_3d_write_raw, 289 }; 290 291 /* Function to push data to buffer */ 292 static void hid_sensor_push_data(struct iio_dev *indio_dev, const void *data) 293 { 294 dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n"); 295 iio_push_to_buffers(indio_dev, data); 296 } 297 298 /* Callback handler to send event after all samples are received and captured */ 299 static int magn_3d_proc_event(struct hid_sensor_hub_device *hsdev, 300 unsigned usage_id, 301 void *priv) 302 { 303 struct iio_dev *indio_dev = platform_get_drvdata(priv); 304 struct magn_3d_state *magn_state = iio_priv(indio_dev); 305 306 dev_dbg(&indio_dev->dev, "magn_3d_proc_event\n"); 307 if (atomic_read(&magn_state->magn_flux_attributes.data_ready)) 308 hid_sensor_push_data(indio_dev, magn_state->iio_vals); 309 310 return 0; 311 } 312 313 /* Capture samples in local storage */ 314 static int magn_3d_capture_sample(struct hid_sensor_hub_device *hsdev, 315 unsigned usage_id, 316 size_t raw_len, char *raw_data, 317 void *priv) 318 { 319 struct iio_dev *indio_dev = platform_get_drvdata(priv); 320 struct magn_3d_state *magn_state = iio_priv(indio_dev); 321 int offset; 322 int ret = 0; 323 u32 *iio_val = NULL; 324 325 switch (usage_id) { 326 case HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS: 327 case HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Y_AXIS: 328 case HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Z_AXIS: 329 offset = (usage_id - HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS) 330 + CHANNEL_SCAN_INDEX_X; 331 break; 332 case HID_USAGE_SENSOR_ORIENT_COMP_MAGN_NORTH: 333 case HID_USAGE_SENSOR_ORIENT_COMP_TRUE_NORTH: 334 case HID_USAGE_SENSOR_ORIENT_MAGN_NORTH: 335 case HID_USAGE_SENSOR_ORIENT_TRUE_NORTH: 336 offset = (usage_id - HID_USAGE_SENSOR_ORIENT_COMP_MAGN_NORTH) 337 + CHANNEL_SCAN_INDEX_NORTH_MAGN_TILT_COMP; 338 break; 339 default: 340 return -EINVAL; 341 } 342 343 iio_val = magn_state->magn_val_addr[offset]; 344 345 if (iio_val != NULL) 346 *iio_val = *((u32 *)raw_data); 347 else 348 ret = -EINVAL; 349 350 return ret; 351 } 352 353 /* Parse report which is specific to an usage id*/ 354 static int magn_3d_parse_report(struct platform_device *pdev, 355 struct hid_sensor_hub_device *hsdev, 356 struct iio_chan_spec **channels, 357 int *chan_count, 358 unsigned usage_id, 359 struct magn_3d_state *st) 360 { 361 int i; 362 int attr_count = 0; 363 struct iio_chan_spec *_channels; 364 365 /* Scan for each usage attribute supported */ 366 for (i = 0; i < MAGN_3D_CHANNEL_MAX; i++) { 367 int status; 368 u32 address = magn_3d_addresses[i]; 369 370 /* Check if usage attribute exists in the sensor hub device */ 371 status = sensor_hub_input_get_attribute_info(hsdev, 372 HID_INPUT_REPORT, 373 usage_id, 374 address, 375 &(st->magn[i])); 376 if (!status) 377 attr_count++; 378 } 379 380 if (attr_count <= 0) { 381 dev_err(&pdev->dev, 382 "failed to find any supported usage attributes in report\n"); 383 return -EINVAL; 384 } 385 386 dev_dbg(&pdev->dev, "magn_3d Found %d usage attributes\n", 387 attr_count); 388 dev_dbg(&pdev->dev, "magn_3d X: %x:%x Y: %x:%x Z: %x:%x\n", 389 st->magn[0].index, 390 st->magn[0].report_id, 391 st->magn[1].index, st->magn[1].report_id, 392 st->magn[2].index, st->magn[2].report_id); 393 394 /* Setup IIO channel array */ 395 _channels = devm_kcalloc(&pdev->dev, attr_count, 396 sizeof(struct iio_chan_spec), 397 GFP_KERNEL); 398 if (!_channels) { 399 dev_err(&pdev->dev, 400 "failed to allocate space for iio channels\n"); 401 return -ENOMEM; 402 } 403 404 st->iio_vals = devm_kcalloc(&pdev->dev, attr_count, 405 sizeof(u32), 406 GFP_KERNEL); 407 if (!st->iio_vals) { 408 dev_err(&pdev->dev, 409 "failed to allocate space for iio values array\n"); 410 return -ENOMEM; 411 } 412 413 for (i = 0, *chan_count = 0; 414 i < MAGN_3D_CHANNEL_MAX && *chan_count < attr_count; 415 i++){ 416 if (st->magn[i].index >= 0) { 417 /* Setup IIO channel struct */ 418 (_channels[*chan_count]) = magn_3d_channels[i]; 419 (_channels[*chan_count]).scan_index = *chan_count; 420 (_channels[*chan_count]).address = i; 421 422 /* Set magn_val_addr to iio value address */ 423 st->magn_val_addr[i] = &(st->iio_vals[*chan_count]); 424 magn_3d_adjust_channel_bit_mask(_channels, 425 *chan_count, 426 st->magn[i].size); 427 (*chan_count)++; 428 } 429 } 430 431 if (*chan_count <= 0) { 432 dev_err(&pdev->dev, 433 "failed to find any magnetic channels setup\n"); 434 return -EINVAL; 435 } 436 437 *channels = _channels; 438 439 dev_dbg(&pdev->dev, "magn_3d Setup %d IIO channels\n", 440 *chan_count); 441 442 st->magn_flux_attr.scale_precision = hid_sensor_format_scale( 443 HID_USAGE_SENSOR_COMPASS_3D, 444 &st->magn[CHANNEL_SCAN_INDEX_X], 445 &st->magn_flux_attr.scale_pre_decml, 446 &st->magn_flux_attr.scale_post_decml); 447 st->rot_attr.scale_precision 448 = hid_sensor_format_scale( 449 HID_USAGE_SENSOR_ORIENT_COMP_MAGN_NORTH, 450 &st->magn[CHANNEL_SCAN_INDEX_NORTH_MAGN_TILT_COMP], 451 &st->rot_attr.scale_pre_decml, 452 &st->rot_attr.scale_post_decml); 453 454 /* Set Sensitivity field ids, when there is no individual modifier */ 455 if (st->magn_flux_attributes.sensitivity.index < 0) { 456 sensor_hub_input_get_attribute_info(hsdev, 457 HID_FEATURE_REPORT, usage_id, 458 HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS | 459 HID_USAGE_SENSOR_DATA_ORIENTATION, 460 &st->magn_flux_attributes.sensitivity); 461 dev_dbg(&pdev->dev, "Sensitivity index:report %d:%d\n", 462 st->magn_flux_attributes.sensitivity.index, 463 st->magn_flux_attributes.sensitivity.report_id); 464 } 465 if (st->magn_flux_attributes.sensitivity.index < 0) { 466 sensor_hub_input_get_attribute_info(hsdev, 467 HID_FEATURE_REPORT, usage_id, 468 HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS | 469 HID_USAGE_SENSOR_ORIENT_MAGN_FLUX, 470 &st->magn_flux_attributes.sensitivity); 471 dev_dbg(&pdev->dev, "Sensitivity index:report %d:%d\n", 472 st->magn_flux_attributes.sensitivity.index, 473 st->magn_flux_attributes.sensitivity.report_id); 474 } 475 if (st->rot_attributes.sensitivity.index < 0) { 476 sensor_hub_input_get_attribute_info(hsdev, 477 HID_FEATURE_REPORT, usage_id, 478 HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS | 479 HID_USAGE_SENSOR_ORIENT_COMP_MAGN_NORTH, 480 &st->rot_attributes.sensitivity); 481 dev_dbg(&pdev->dev, "Sensitivity index:report %d:%d\n", 482 st->rot_attributes.sensitivity.index, 483 st->rot_attributes.sensitivity.report_id); 484 } 485 486 return 0; 487 } 488 489 /* Function to initialize the processing for usage id */ 490 static int hid_magn_3d_probe(struct platform_device *pdev) 491 { 492 int ret = 0; 493 static char *name = "magn_3d"; 494 struct iio_dev *indio_dev; 495 struct magn_3d_state *magn_state; 496 struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; 497 struct iio_chan_spec *channels; 498 int chan_count = 0; 499 500 indio_dev = devm_iio_device_alloc(&pdev->dev, 501 sizeof(struct magn_3d_state)); 502 if (indio_dev == NULL) 503 return -ENOMEM; 504 505 platform_set_drvdata(pdev, indio_dev); 506 507 magn_state = iio_priv(indio_dev); 508 magn_state->magn_flux_attributes.hsdev = hsdev; 509 magn_state->magn_flux_attributes.pdev = pdev; 510 511 ret = hid_sensor_parse_common_attributes(hsdev, 512 HID_USAGE_SENSOR_COMPASS_3D, 513 &magn_state->magn_flux_attributes); 514 if (ret) { 515 dev_err(&pdev->dev, "failed to setup common attributes\n"); 516 return ret; 517 } 518 magn_state->rot_attributes = magn_state->magn_flux_attributes; 519 520 ret = magn_3d_parse_report(pdev, hsdev, 521 &channels, &chan_count, 522 HID_USAGE_SENSOR_COMPASS_3D, magn_state); 523 if (ret) { 524 dev_err(&pdev->dev, "failed to parse report\n"); 525 return ret; 526 } 527 528 indio_dev->channels = channels; 529 indio_dev->num_channels = chan_count; 530 indio_dev->dev.parent = &pdev->dev; 531 indio_dev->info = &magn_3d_info; 532 indio_dev->name = name; 533 indio_dev->modes = INDIO_DIRECT_MODE; 534 535 ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, 536 NULL, NULL); 537 if (ret) { 538 dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); 539 return ret; 540 } 541 atomic_set(&magn_state->magn_flux_attributes.data_ready, 0); 542 ret = hid_sensor_setup_trigger(indio_dev, name, 543 &magn_state->magn_flux_attributes); 544 if (ret < 0) { 545 dev_err(&pdev->dev, "trigger setup failed\n"); 546 goto error_unreg_buffer_funcs; 547 } 548 549 ret = iio_device_register(indio_dev); 550 if (ret) { 551 dev_err(&pdev->dev, "device register failed\n"); 552 goto error_remove_trigger; 553 } 554 555 magn_state->callbacks.send_event = magn_3d_proc_event; 556 magn_state->callbacks.capture_sample = magn_3d_capture_sample; 557 magn_state->callbacks.pdev = pdev; 558 ret = sensor_hub_register_callback(hsdev, HID_USAGE_SENSOR_COMPASS_3D, 559 &magn_state->callbacks); 560 if (ret < 0) { 561 dev_err(&pdev->dev, "callback reg failed\n"); 562 goto error_iio_unreg; 563 } 564 565 return ret; 566 567 error_iio_unreg: 568 iio_device_unregister(indio_dev); 569 error_remove_trigger: 570 hid_sensor_remove_trigger(&magn_state->magn_flux_attributes); 571 error_unreg_buffer_funcs: 572 iio_triggered_buffer_cleanup(indio_dev); 573 return ret; 574 } 575 576 /* Function to deinitialize the processing for usage id */ 577 static int hid_magn_3d_remove(struct platform_device *pdev) 578 { 579 struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; 580 struct iio_dev *indio_dev = platform_get_drvdata(pdev); 581 struct magn_3d_state *magn_state = iio_priv(indio_dev); 582 583 sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_COMPASS_3D); 584 iio_device_unregister(indio_dev); 585 hid_sensor_remove_trigger(&magn_state->magn_flux_attributes); 586 iio_triggered_buffer_cleanup(indio_dev); 587 588 return 0; 589 } 590 591 static const struct platform_device_id hid_magn_3d_ids[] = { 592 { 593 /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ 594 .name = "HID-SENSOR-200083", 595 }, 596 { /* sentinel */ } 597 }; 598 MODULE_DEVICE_TABLE(platform, hid_magn_3d_ids); 599 600 static struct platform_driver hid_magn_3d_platform_driver = { 601 .id_table = hid_magn_3d_ids, 602 .driver = { 603 .name = KBUILD_MODNAME, 604 .pm = &hid_sensor_pm_ops, 605 }, 606 .probe = hid_magn_3d_probe, 607 .remove = hid_magn_3d_remove, 608 }; 609 module_platform_driver(hid_magn_3d_platform_driver); 610 611 MODULE_DESCRIPTION("HID Sensor Magnetometer 3D"); 612 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>"); 613 MODULE_LICENSE("GPL"); 614