1 // SPDX-License-Identifier: GPL-2.0-only
4 * Copyright (c) 2012, Intel Corporation.
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/slab.h>
11 #include <linux/hid-sensor-hub.h>
12 #include <linux/iio/iio.h>
13 #include <linux/iio/buffer.h>
14 #include "../common/hid-sensors/hid-sensor-trigger.h"
16 enum gyro_3d_channel
{
23 #define CHANNEL_SCAN_INDEX_TIMESTAMP GYRO_3D_CHANNEL_MAX
24 struct gyro_3d_state
{
25 struct hid_sensor_hub_callbacks callbacks
;
26 struct hid_sensor_common common_attributes
;
27 struct hid_sensor_hub_attribute_info gyro
[GYRO_3D_CHANNEL_MAX
];
29 u32 gyro_val
[GYRO_3D_CHANNEL_MAX
];
30 u64 timestamp
__aligned(8);
39 static const u32 gyro_3d_addresses
[GYRO_3D_CHANNEL_MAX
] = {
40 HID_USAGE_SENSOR_ANGL_VELOCITY_X_AXIS
,
41 HID_USAGE_SENSOR_ANGL_VELOCITY_Y_AXIS
,
42 HID_USAGE_SENSOR_ANGL_VELOCITY_Z_AXIS
45 static const u32 gryo_3d_sensitivity_addresses
[] = {
46 HID_USAGE_SENSOR_DATA_ANGL_VELOCITY
,
49 /* Channel definitions */
50 static const struct iio_chan_spec gyro_3d_channels
[] = {
54 .channel2
= IIO_MOD_X
,
55 .info_mask_separate
= BIT(IIO_CHAN_INFO_RAW
),
56 .info_mask_shared_by_type
= BIT(IIO_CHAN_INFO_OFFSET
) |
57 BIT(IIO_CHAN_INFO_SCALE
) |
58 BIT(IIO_CHAN_INFO_SAMP_FREQ
) |
59 BIT(IIO_CHAN_INFO_HYSTERESIS
),
60 .scan_index
= CHANNEL_SCAN_INDEX_X
,
64 .channel2
= IIO_MOD_Y
,
65 .info_mask_separate
= BIT(IIO_CHAN_INFO_RAW
),
66 .info_mask_shared_by_type
= BIT(IIO_CHAN_INFO_OFFSET
) |
67 BIT(IIO_CHAN_INFO_SCALE
) |
68 BIT(IIO_CHAN_INFO_SAMP_FREQ
) |
69 BIT(IIO_CHAN_INFO_HYSTERESIS
),
70 .scan_index
= CHANNEL_SCAN_INDEX_Y
,
74 .channel2
= IIO_MOD_Z
,
75 .info_mask_separate
= BIT(IIO_CHAN_INFO_RAW
),
76 .info_mask_shared_by_type
= BIT(IIO_CHAN_INFO_OFFSET
) |
77 BIT(IIO_CHAN_INFO_SCALE
) |
78 BIT(IIO_CHAN_INFO_SAMP_FREQ
) |
79 BIT(IIO_CHAN_INFO_HYSTERESIS
),
80 .scan_index
= CHANNEL_SCAN_INDEX_Z
,
82 IIO_CHAN_SOFT_TIMESTAMP(CHANNEL_SCAN_INDEX_TIMESTAMP
)
85 /* Adjust channel real bits based on report descriptor */
86 static void gyro_3d_adjust_channel_bit_mask(struct iio_chan_spec
*channels
,
87 int channel
, int size
)
89 channels
[channel
].scan_type
.sign
= 's';
90 /* Real storage bits will change based on the report desc. */
91 channels
[channel
].scan_type
.realbits
= size
* 8;
92 /* Maximum size of a sample to capture is u32 */
93 channels
[channel
].scan_type
.storagebits
= sizeof(u32
) * 8;
96 /* Channel read_raw handler */
97 static int gyro_3d_read_raw(struct iio_dev
*indio_dev
,
98 struct iio_chan_spec
const *chan
,
102 struct gyro_3d_state
*gyro_state
= iio_priv(indio_dev
);
111 case IIO_CHAN_INFO_RAW
:
112 hid_sensor_power_state(&gyro_state
->common_attributes
, true);
113 report_id
= gyro_state
->gyro
[chan
->scan_index
].report_id
;
114 min
= gyro_state
->gyro
[chan
->scan_index
].logical_minimum
;
115 address
= gyro_3d_addresses
[chan
->scan_index
];
117 *val
= sensor_hub_input_attr_get_raw_value(
118 gyro_state
->common_attributes
.hsdev
,
119 HID_USAGE_SENSOR_GYRO_3D
, address
,
125 hid_sensor_power_state(&gyro_state
->common_attributes
,
129 hid_sensor_power_state(&gyro_state
->common_attributes
, false);
130 ret_type
= IIO_VAL_INT
;
132 case IIO_CHAN_INFO_SCALE
:
133 *val
= gyro_state
->scale_pre_decml
;
134 *val2
= gyro_state
->scale_post_decml
;
135 ret_type
= gyro_state
->scale_precision
;
137 case IIO_CHAN_INFO_OFFSET
:
138 *val
= gyro_state
->value_offset
;
139 ret_type
= IIO_VAL_INT
;
141 case IIO_CHAN_INFO_SAMP_FREQ
:
142 ret_type
= hid_sensor_read_samp_freq_value(
143 &gyro_state
->common_attributes
, val
, val2
);
145 case IIO_CHAN_INFO_HYSTERESIS
:
146 ret_type
= hid_sensor_read_raw_hyst_value(
147 &gyro_state
->common_attributes
, val
, val2
);
157 /* Channel write_raw handler */
158 static int gyro_3d_write_raw(struct iio_dev
*indio_dev
,
159 struct iio_chan_spec
const *chan
,
164 struct gyro_3d_state
*gyro_state
= iio_priv(indio_dev
);
168 case IIO_CHAN_INFO_SAMP_FREQ
:
169 ret
= hid_sensor_write_samp_freq_value(
170 &gyro_state
->common_attributes
, val
, val2
);
172 case IIO_CHAN_INFO_HYSTERESIS
:
173 ret
= hid_sensor_write_raw_hyst_value(
174 &gyro_state
->common_attributes
, val
, val2
);
183 static const struct iio_info gyro_3d_info
= {
184 .read_raw
= &gyro_3d_read_raw
,
185 .write_raw
= &gyro_3d_write_raw
,
188 /* Callback handler to send event after all samples are received and captured */
189 static int gyro_3d_proc_event(struct hid_sensor_hub_device
*hsdev
,
193 struct iio_dev
*indio_dev
= platform_get_drvdata(priv
);
194 struct gyro_3d_state
*gyro_state
= iio_priv(indio_dev
);
196 dev_dbg(&indio_dev
->dev
, "gyro_3d_proc_event\n");
197 if (atomic_read(&gyro_state
->common_attributes
.data_ready
)) {
198 if (!gyro_state
->timestamp
)
199 gyro_state
->timestamp
= iio_get_time_ns(indio_dev
);
201 iio_push_to_buffers_with_timestamp(indio_dev
, &gyro_state
->scan
,
202 gyro_state
->timestamp
);
204 gyro_state
->timestamp
= 0;
210 /* Capture samples in local storage */
211 static int gyro_3d_capture_sample(struct hid_sensor_hub_device
*hsdev
,
213 size_t raw_len
, char *raw_data
,
216 struct iio_dev
*indio_dev
= platform_get_drvdata(priv
);
217 struct gyro_3d_state
*gyro_state
= iio_priv(indio_dev
);
222 case HID_USAGE_SENSOR_ANGL_VELOCITY_X_AXIS
:
223 case HID_USAGE_SENSOR_ANGL_VELOCITY_Y_AXIS
:
224 case HID_USAGE_SENSOR_ANGL_VELOCITY_Z_AXIS
:
225 offset
= usage_id
- HID_USAGE_SENSOR_ANGL_VELOCITY_X_AXIS
;
226 gyro_state
->scan
.gyro_val
[CHANNEL_SCAN_INDEX_X
+ offset
] =
230 case HID_USAGE_SENSOR_TIME_TIMESTAMP
:
231 gyro_state
->timestamp
=
232 hid_sensor_convert_timestamp(&gyro_state
->common_attributes
,
243 /* Parse report which is specific to an usage id*/
244 static int gyro_3d_parse_report(struct platform_device
*pdev
,
245 struct hid_sensor_hub_device
*hsdev
,
246 struct iio_chan_spec
*channels
,
248 struct gyro_3d_state
*st
)
253 for (i
= 0; i
<= CHANNEL_SCAN_INDEX_Z
; ++i
) {
254 ret
= sensor_hub_input_get_attribute_info(hsdev
,
257 HID_USAGE_SENSOR_ANGL_VELOCITY_X_AXIS
+ i
,
258 &st
->gyro
[CHANNEL_SCAN_INDEX_X
+ i
]);
261 gyro_3d_adjust_channel_bit_mask(channels
,
262 CHANNEL_SCAN_INDEX_X
+ i
,
263 st
->gyro
[CHANNEL_SCAN_INDEX_X
+ i
].size
);
265 dev_dbg(&pdev
->dev
, "gyro_3d %x:%x, %x:%x, %x:%x\n",
267 st
->gyro
[0].report_id
,
268 st
->gyro
[1].index
, st
->gyro
[1].report_id
,
269 st
->gyro
[2].index
, st
->gyro
[2].report_id
);
271 st
->scale_precision
= hid_sensor_format_scale(
272 HID_USAGE_SENSOR_GYRO_3D
,
273 &st
->gyro
[CHANNEL_SCAN_INDEX_X
],
274 &st
->scale_pre_decml
, &st
->scale_post_decml
);
279 /* Function to initialize the processing for usage id */
280 static int hid_gyro_3d_probe(struct platform_device
*pdev
)
283 static const char *name
= "gyro_3d";
284 struct iio_dev
*indio_dev
;
285 struct gyro_3d_state
*gyro_state
;
286 struct hid_sensor_hub_device
*hsdev
= pdev
->dev
.platform_data
;
288 indio_dev
= devm_iio_device_alloc(&pdev
->dev
, sizeof(*gyro_state
));
291 platform_set_drvdata(pdev
, indio_dev
);
293 gyro_state
= iio_priv(indio_dev
);
294 gyro_state
->common_attributes
.hsdev
= hsdev
;
295 gyro_state
->common_attributes
.pdev
= pdev
;
297 ret
= hid_sensor_parse_common_attributes(hsdev
,
298 HID_USAGE_SENSOR_GYRO_3D
,
299 &gyro_state
->common_attributes
,
300 gryo_3d_sensitivity_addresses
,
301 ARRAY_SIZE(gryo_3d_sensitivity_addresses
));
303 dev_err(&pdev
->dev
, "failed to setup common attributes\n");
307 indio_dev
->channels
= devm_kmemdup(&pdev
->dev
, gyro_3d_channels
,
308 sizeof(gyro_3d_channels
), GFP_KERNEL
);
309 if (!indio_dev
->channels
) {
310 dev_err(&pdev
->dev
, "failed to duplicate channels\n");
314 ret
= gyro_3d_parse_report(pdev
, hsdev
,
315 (struct iio_chan_spec
*)indio_dev
->channels
,
316 HID_USAGE_SENSOR_GYRO_3D
, gyro_state
);
318 dev_err(&pdev
->dev
, "failed to setup attributes\n");
322 indio_dev
->num_channels
= ARRAY_SIZE(gyro_3d_channels
);
323 indio_dev
->info
= &gyro_3d_info
;
324 indio_dev
->name
= name
;
325 indio_dev
->modes
= INDIO_DIRECT_MODE
;
327 atomic_set(&gyro_state
->common_attributes
.data_ready
, 0);
329 ret
= hid_sensor_setup_trigger(indio_dev
, name
,
330 &gyro_state
->common_attributes
);
332 dev_err(&pdev
->dev
, "trigger setup failed\n");
336 ret
= iio_device_register(indio_dev
);
338 dev_err(&pdev
->dev
, "device register failed\n");
339 goto error_remove_trigger
;
342 gyro_state
->callbacks
.send_event
= gyro_3d_proc_event
;
343 gyro_state
->callbacks
.capture_sample
= gyro_3d_capture_sample
;
344 gyro_state
->callbacks
.pdev
= pdev
;
345 ret
= sensor_hub_register_callback(hsdev
, HID_USAGE_SENSOR_GYRO_3D
,
346 &gyro_state
->callbacks
);
348 dev_err(&pdev
->dev
, "callback reg failed\n");
349 goto error_iio_unreg
;
355 iio_device_unregister(indio_dev
);
356 error_remove_trigger
:
357 hid_sensor_remove_trigger(indio_dev
, &gyro_state
->common_attributes
);
361 /* Function to deinitialize the processing for usage id */
362 static void hid_gyro_3d_remove(struct platform_device
*pdev
)
364 struct hid_sensor_hub_device
*hsdev
= pdev
->dev
.platform_data
;
365 struct iio_dev
*indio_dev
= platform_get_drvdata(pdev
);
366 struct gyro_3d_state
*gyro_state
= iio_priv(indio_dev
);
368 sensor_hub_remove_callback(hsdev
, HID_USAGE_SENSOR_GYRO_3D
);
369 iio_device_unregister(indio_dev
);
370 hid_sensor_remove_trigger(indio_dev
, &gyro_state
->common_attributes
);
373 static const struct platform_device_id hid_gyro_3d_ids
[] = {
375 /* Format: HID-SENSOR-usage_id_in_hex_lowercase */
376 .name
= "HID-SENSOR-200076",
380 MODULE_DEVICE_TABLE(platform
, hid_gyro_3d_ids
);
382 static struct platform_driver hid_gyro_3d_platform_driver
= {
383 .id_table
= hid_gyro_3d_ids
,
385 .name
= KBUILD_MODNAME
,
386 .pm
= &hid_sensor_pm_ops
,
388 .probe
= hid_gyro_3d_probe
,
389 .remove_new
= hid_gyro_3d_remove
,
391 module_platform_driver(hid_gyro_3d_platform_driver
);
393 MODULE_DESCRIPTION("HID Sensor Gyroscope 3D");
394 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>");
395 MODULE_LICENSE("GPL");
396 MODULE_IMPORT_NS(IIO_HID
);