xref: /linux/drivers/iio/pressure/hid-sensor-press.c (revision 3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * HID Sensors Driver
4  * Copyright (c) 2014, Intel Corporation.
5  */
6 #include <linux/bitops.h>
7 #include <linux/device.h>
8 #include <linux/platform_device.h>
9 #include <linux/module.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"
15 
16 enum {
17 	CHANNEL_SCAN_INDEX_PRESSURE,
18 	CHANNEL_SCAN_INDEX_TIMESTAMP,
19 };
20 
21 struct press_state {
22 	struct hid_sensor_hub_callbacks callbacks;
23 	struct hid_sensor_common common_attributes;
24 	struct hid_sensor_hub_attribute_info press_attr;
25 	struct {
26 		u32 press_data;
27 		aligned_s64 timestamp;
28 	} scan;
29 	int scale_pre_decml;
30 	int scale_post_decml;
31 	int scale_precision;
32 	int value_offset;
33 	s64 timestamp;
34 };
35 
36 static const u32 press_sensitivity_addresses[] = {
37 	HID_USAGE_SENSOR_DATA_ATMOSPHERIC_PRESSURE,
38 	HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE
39 };
40 
41 /* Channel definitions */
42 static const struct iio_chan_spec press_channels[] = {
43 	{
44 		.type = IIO_PRESSURE,
45 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
46 		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
47 		BIT(IIO_CHAN_INFO_SCALE) |
48 		BIT(IIO_CHAN_INFO_SAMP_FREQ) |
49 		BIT(IIO_CHAN_INFO_HYSTERESIS),
50 		.scan_index = CHANNEL_SCAN_INDEX_PRESSURE,
51 	},
52 	IIO_CHAN_SOFT_TIMESTAMP(CHANNEL_SCAN_INDEX_TIMESTAMP)
53 
54 };
55 
56 /* Channel read_raw handler */
57 static int press_read_raw(struct iio_dev *indio_dev,
58 			  struct iio_chan_spec const *chan,
59 			  int *val, int *val2, long mask)
60 {
61 	struct press_state *press_state = iio_priv(indio_dev);
62 	int report_id = -1;
63 	u32 address;
64 	int ret_type;
65 	s32 min;
66 
67 	*val = 0;
68 	*val2 = 0;
69 	switch (mask) {
70 	case IIO_CHAN_INFO_RAW:
71 		switch (chan->scan_index) {
72 		case  CHANNEL_SCAN_INDEX_PRESSURE:
73 			report_id = press_state->press_attr.report_id;
74 			min = press_state->press_attr.logical_minimum;
75 			address = HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE;
76 			break;
77 		default:
78 			report_id = -1;
79 			break;
80 		}
81 		if (report_id >= 0) {
82 			hid_sensor_power_state(&press_state->common_attributes,
83 					       true);
84 			*val = sensor_hub_input_attr_get_raw_value(
85 				press_state->common_attributes.hsdev,
86 				HID_USAGE_SENSOR_PRESSURE, address,
87 				report_id,
88 				SENSOR_HUB_SYNC,
89 				min < 0);
90 			hid_sensor_power_state(&press_state->common_attributes,
91 					       false);
92 		} else {
93 			*val = 0;
94 			return -EINVAL;
95 		}
96 		ret_type = IIO_VAL_INT;
97 		break;
98 	case IIO_CHAN_INFO_SCALE:
99 		*val = press_state->scale_pre_decml;
100 		*val2 = press_state->scale_post_decml;
101 		ret_type = press_state->scale_precision;
102 		break;
103 	case IIO_CHAN_INFO_OFFSET:
104 		*val = press_state->value_offset;
105 		ret_type = IIO_VAL_INT;
106 		break;
107 	case IIO_CHAN_INFO_SAMP_FREQ:
108 		ret_type = hid_sensor_read_samp_freq_value(
109 				&press_state->common_attributes, val, val2);
110 		break;
111 	case IIO_CHAN_INFO_HYSTERESIS:
112 		ret_type = hid_sensor_read_raw_hyst_value(
113 				&press_state->common_attributes, val, val2);
114 		break;
115 	default:
116 		ret_type = -EINVAL;
117 		break;
118 	}
119 
120 	return ret_type;
121 }
122 
123 /* Channel write_raw handler */
124 static int press_write_raw(struct iio_dev *indio_dev,
125 			   struct iio_chan_spec const *chan,
126 			   int val, int val2, long mask)
127 {
128 	struct press_state *press_state = iio_priv(indio_dev);
129 	int ret = 0;
130 
131 	switch (mask) {
132 	case IIO_CHAN_INFO_SAMP_FREQ:
133 		ret = hid_sensor_write_samp_freq_value(
134 				&press_state->common_attributes, val, val2);
135 		break;
136 	case IIO_CHAN_INFO_HYSTERESIS:
137 		ret = hid_sensor_write_raw_hyst_value(
138 				&press_state->common_attributes, val, val2);
139 		break;
140 	default:
141 		ret = -EINVAL;
142 	}
143 
144 	return ret;
145 }
146 
147 static const struct iio_info press_info = {
148 	.read_raw = &press_read_raw,
149 	.write_raw = &press_write_raw,
150 };
151 
152 /* Callback handler to send event after all samples are received and captured */
153 static int press_proc_event(struct hid_sensor_hub_device *hsdev,
154 			    u32 usage_id, void *priv)
155 {
156 	struct iio_dev *indio_dev = platform_get_drvdata(priv);
157 	struct press_state *press_state = iio_priv(indio_dev);
158 
159 	dev_dbg(&indio_dev->dev, "press_proc_event\n");
160 	if (atomic_read(&press_state->common_attributes.data_ready)) {
161 		if (!press_state->timestamp)
162 			press_state->timestamp = iio_get_time_ns(indio_dev);
163 
164 		iio_push_to_buffers_with_ts(indio_dev, &press_state->scan,
165 					    sizeof(press_state->scan),
166 					    press_state->timestamp);
167 	}
168 
169 	return 0;
170 }
171 
172 /* Capture samples in local storage */
173 static int press_capture_sample(struct hid_sensor_hub_device *hsdev,
174 				u32 usage_id,
175 				size_t raw_len, char *raw_data,
176 				void *priv)
177 {
178 	struct iio_dev *indio_dev = platform_get_drvdata(priv);
179 	struct press_state *press_state = iio_priv(indio_dev);
180 	int ret = -EINVAL;
181 
182 	switch (usage_id) {
183 	case HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE:
184 		press_state->scan.press_data = *(u32 *)raw_data;
185 		ret = 0;
186 		break;
187 	case HID_USAGE_SENSOR_TIME_TIMESTAMP:
188 		press_state->timestamp = hid_sensor_convert_timestamp(
189 			&press_state->common_attributes, *(s64 *)raw_data);
190 		break;
191 	default:
192 		break;
193 	}
194 
195 	return ret;
196 }
197 
198 /* Parse report which is specific to an usage id*/
199 static int press_parse_report(struct platform_device *pdev,
200 			      struct hid_sensor_hub_device *hsdev,
201 			      struct iio_chan_spec *channels,
202 			      u32 usage_id,
203 			      struct press_state *st)
204 {
205 	int ret;
206 
207 	ret = sensor_hub_input_get_attribute_info(hsdev, HID_INPUT_REPORT,
208 			usage_id,
209 			HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE,
210 			&st->press_attr);
211 	if (ret < 0)
212 		return ret;
213 	channels[CHANNEL_SCAN_INDEX_PRESSURE].scan_type = (struct iio_scan_type) {
214 		.format = 's',
215 		.realbits = BYTES_TO_BITS(st->press_attr.size),
216 		.storagebits = BITS_PER_TYPE(u32),
217 	};
218 
219 	dev_dbg(&pdev->dev, "press %x:%x\n", st->press_attr.index,
220 		st->press_attr.report_id);
221 
222 	st->scale_precision = hid_sensor_format_scale(
223 				HID_USAGE_SENSOR_PRESSURE,
224 				&st->press_attr,
225 				&st->scale_pre_decml, &st->scale_post_decml);
226 
227 	return ret;
228 }
229 
230 /* Function to initialize the processing for usage id */
231 static int hid_press_probe(struct platform_device *pdev)
232 {
233 	struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
234 	int ret = 0;
235 	static const char *name = "press";
236 	struct iio_dev *indio_dev;
237 	struct press_state *press_state;
238 
239 	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct press_state));
240 	if (!indio_dev)
241 		return -ENOMEM;
242 	platform_set_drvdata(pdev, indio_dev);
243 
244 	press_state = iio_priv(indio_dev);
245 	press_state->common_attributes.hsdev = hsdev;
246 	press_state->common_attributes.pdev = pdev;
247 
248 	ret = hid_sensor_parse_common_attributes(hsdev,
249 					HID_USAGE_SENSOR_PRESSURE,
250 					&press_state->common_attributes,
251 					press_sensitivity_addresses,
252 					ARRAY_SIZE(press_sensitivity_addresses));
253 	if (ret) {
254 		dev_err(&pdev->dev, "failed to setup common attributes\n");
255 		return ret;
256 	}
257 
258 	indio_dev->channels = devm_kmemdup(&pdev->dev, press_channels,
259 					   sizeof(press_channels), GFP_KERNEL);
260 	if (!indio_dev->channels) {
261 		dev_err(&pdev->dev, "failed to duplicate channels\n");
262 		return -ENOMEM;
263 	}
264 
265 	ret = press_parse_report(pdev, hsdev,
266 				 (struct iio_chan_spec *)indio_dev->channels,
267 				 HID_USAGE_SENSOR_PRESSURE, press_state);
268 	if (ret) {
269 		dev_err(&pdev->dev, "failed to setup attributes\n");
270 		return ret;
271 	}
272 
273 	indio_dev->num_channels =
274 				ARRAY_SIZE(press_channels);
275 	indio_dev->info = &press_info;
276 	indio_dev->name = name;
277 	indio_dev->modes = INDIO_DIRECT_MODE;
278 
279 	atomic_set(&press_state->common_attributes.data_ready, 0);
280 
281 	ret = hid_sensor_setup_trigger(indio_dev, name,
282 				       &press_state->common_attributes);
283 	if (ret) {
284 		dev_err(&pdev->dev, "trigger setup failed\n");
285 		return ret;
286 	}
287 
288 	press_state->callbacks.send_event = press_proc_event;
289 	press_state->callbacks.capture_sample = press_capture_sample;
290 	press_state->callbacks.pdev = pdev;
291 	ret = sensor_hub_register_callback(hsdev, HID_USAGE_SENSOR_PRESSURE,
292 					   &press_state->callbacks);
293 	if (ret < 0) {
294 		dev_err(&pdev->dev, "callback reg failed\n");
295 		goto error_remove_trigger;
296 	}
297 
298 	ret = iio_device_register(indio_dev);
299 	if (ret) {
300 		dev_err(&pdev->dev, "device register failed\n");
301 		goto error_remove_callback;
302 	}
303 
304 	return ret;
305 
306 error_remove_callback:
307 	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_PRESSURE);
308 error_remove_trigger:
309 	hid_sensor_remove_trigger(indio_dev, &press_state->common_attributes);
310 	return ret;
311 }
312 
313 /* Function to deinitialize the processing for usage id */
314 static void hid_press_remove(struct platform_device *pdev)
315 {
316 	struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
317 	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
318 	struct press_state *press_state = iio_priv(indio_dev);
319 
320 	iio_device_unregister(indio_dev);
321 	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_PRESSURE);
322 	hid_sensor_remove_trigger(indio_dev, &press_state->common_attributes);
323 }
324 
325 static const struct platform_device_id hid_press_ids[] = {
326 	{
327 		/* Format: HID-SENSOR-usage_id_in_hex_lowercase */
328 		.name = "HID-SENSOR-200031",
329 	},
330 	{ }
331 };
332 MODULE_DEVICE_TABLE(platform, hid_press_ids);
333 
334 static struct platform_driver hid_press_platform_driver = {
335 	.id_table = hid_press_ids,
336 	.driver = {
337 		.name	= KBUILD_MODNAME,
338 		.pm	= &hid_sensor_pm_ops,
339 	},
340 	.probe		= hid_press_probe,
341 	.remove		= hid_press_remove,
342 };
343 module_platform_driver(hid_press_platform_driver);
344 
345 MODULE_DESCRIPTION("HID Sensor Pressure");
346 MODULE_AUTHOR("Archana Patni <archana.patni@intel.com>");
347 MODULE_LICENSE("GPL");
348 MODULE_IMPORT_NS("IIO_HID");
349