root/drivers/iio/magnetometer/hid-sensor-magn-3d.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. magn_3d_adjust_channel_bit_mask
  2. magn_3d_read_raw
  3. magn_3d_write_raw
  4. hid_sensor_push_data
  5. magn_3d_proc_event
  6. magn_3d_capture_sample
  7. magn_3d_parse_report
  8. hid_magn_3d_probe
  9. hid_magn_3d_remove

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

/* [<][>][^][v][top][bottom][index][help] */