cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hid-sensor-magn-3d.c (16384B)


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