1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * hid-sensor-custom.c
4 * Copyright (c) 2015, Intel Corporation.
5 */
6
7#include <linux/ctype.h>
8#include <linux/dmi.h>
9#include <linux/kernel.h>
10#include <linux/module.h>
11#include <linux/init.h>
12#include <linux/miscdevice.h>
13#include <linux/kfifo.h>
14#include <linux/sched.h>
15#include <linux/wait.h>
16#include <linux/poll.h>
17#include <linux/bsearch.h>
18#include <linux/platform_device.h>
19#include <linux/hid-sensor-hub.h>
20
21#define HID_CUSTOM_NAME_LENGTH		64
22#define HID_CUSTOM_MAX_CORE_ATTRS	10
23#define HID_CUSTOM_TOTAL_ATTRS		(HID_CUSTOM_MAX_CORE_ATTRS + 1)
24#define HID_CUSTOM_FIFO_SIZE		4096
25#define HID_CUSTOM_MAX_FEATURE_BYTES	64
26#define HID_SENSOR_USAGE_LENGTH (4 + 1)
27
28struct hid_sensor_custom_field {
29	int report_id;
30	char group_name[HID_CUSTOM_NAME_LENGTH];
31	struct hid_sensor_hub_attribute_info attribute;
32	struct device_attribute sd_attrs[HID_CUSTOM_MAX_CORE_ATTRS];
33	char attr_name[HID_CUSTOM_TOTAL_ATTRS][HID_CUSTOM_NAME_LENGTH];
34	struct attribute *attrs[HID_CUSTOM_TOTAL_ATTRS];
35	struct attribute_group hid_custom_attribute_group;
36};
37
38struct hid_sensor_custom {
39	struct mutex mutex;
40	struct platform_device *pdev;
41	struct hid_sensor_hub_device *hsdev;
42	struct hid_sensor_hub_callbacks callbacks;
43	int sensor_field_count;
44	struct hid_sensor_custom_field *fields;
45	int input_field_count;
46	int input_report_size;
47	int input_report_recd_size;
48	bool input_skip_sample;
49	bool enable;
50	struct hid_sensor_custom_field *power_state;
51	struct hid_sensor_custom_field *report_state;
52	struct miscdevice custom_dev;
53	struct kfifo data_fifo;
54	unsigned long misc_opened;
55	wait_queue_head_t wait;
56	struct platform_device *custom_pdev;
57};
58
59/* Header for each sample to user space via dev interface */
60struct hid_sensor_sample {
61	u32 usage_id;
62	u64 timestamp;
63	u32 raw_len;
64} __packed;
65
66static struct attribute hid_custom_attrs[HID_CUSTOM_TOTAL_ATTRS] = {
67	{.name = "name", .mode = S_IRUGO},
68	{.name = "units", .mode = S_IRUGO},
69	{.name = "unit-expo", .mode = S_IRUGO},
70	{.name = "minimum", .mode = S_IRUGO},
71	{.name = "maximum", .mode = S_IRUGO},
72	{.name = "size", .mode = S_IRUGO},
73	{.name = "value", .mode = S_IWUSR | S_IRUGO},
74	{.name = NULL}
75};
76
77static const struct hid_custom_usage_desc {
78	int usage_id;
79	char *desc;
80} hid_custom_usage_desc_table[] = {
81	{0x200201,	"event-sensor-state"},
82	{0x200202,	"event-sensor-event"},
83	{0x200301,	"property-friendly-name"},
84	{0x200302,	"property-persistent-unique-id"},
85	{0x200303,	"property-sensor-status"},
86	{0x200304,	"property-min-report-interval"},
87	{0x200305,	"property-sensor-manufacturer"},
88	{0x200306,	"property-sensor-model"},
89	{0x200307,	"property-sensor-serial-number"},
90	{0x200308,	"property-sensor-description"},
91	{0x200309,	"property-sensor-connection-type"},
92	{0x20030A,	"property-sensor-device-path"},
93	{0x20030B,	"property-hardware-revision"},
94	{0x20030C,	"property-firmware-version"},
95	{0x20030D,	"property-release-date"},
96	{0x20030E,	"property-report-interval"},
97	{0x20030F,	"property-change-sensitivity-absolute"},
98	{0x200310,	"property-change-sensitivity-percent-range"},
99	{0x200311,	"property-change-sensitivity-percent-relative"},
100	{0x200312,	"property-accuracy"},
101	{0x200313,	"property-resolution"},
102	{0x200314,	"property-maximum"},
103	{0x200315,	"property-minimum"},
104	{0x200316,	"property-reporting-state"},
105	{0x200317,	"property-sampling-rate"},
106	{0x200318,	"property-response-curve"},
107	{0x200319,	"property-power-state"},
108	{0x200540,	"data-field-custom"},
109	{0x200541,	"data-field-custom-usage"},
110	{0x200542,	"data-field-custom-boolean-array"},
111	{0x200543,	"data-field-custom-value"},
112	{0x200544,	"data-field-custom-value_1"},
113	{0x200545,	"data-field-custom-value_2"},
114	{0x200546,	"data-field-custom-value_3"},
115	{0x200547,	"data-field-custom-value_4"},
116	{0x200548,	"data-field-custom-value_5"},
117	{0x200549,	"data-field-custom-value_6"},
118	{0x20054A,	"data-field-custom-value_7"},
119	{0x20054B,	"data-field-custom-value_8"},
120	{0x20054C,	"data-field-custom-value_9"},
121	{0x20054D,	"data-field-custom-value_10"},
122	{0x20054E,	"data-field-custom-value_11"},
123	{0x20054F,	"data-field-custom-value_12"},
124	{0x200550,	"data-field-custom-value_13"},
125	{0x200551,	"data-field-custom-value_14"},
126	{0x200552,	"data-field-custom-value_15"},
127	{0x200553,	"data-field-custom-value_16"},
128	{0x200554,	"data-field-custom-value_17"},
129	{0x200555,	"data-field-custom-value_18"},
130	{0x200556,	"data-field-custom-value_19"},
131	{0x200557,	"data-field-custom-value_20"},
132	{0x200558,	"data-field-custom-value_21"},
133	{0x200559,	"data-field-custom-value_22"},
134	{0x20055A,	"data-field-custom-value_23"},
135	{0x20055B,	"data-field-custom-value_24"},
136	{0x20055C,	"data-field-custom-value_25"},
137	{0x20055D,	"data-field-custom-value_26"},
138	{0x20055E,	"data-field-custom-value_27"},
139	{0x20055F,	"data-field-custom-value_28"},
140};
141
142static int usage_id_cmp(const void *p1, const void *p2)
143{
144	if (*(int *)p1 < *(int *)p2)
145		return -1;
146
147	if (*(int *)p1 > *(int *)p2)
148		return 1;
149
150	return 0;
151}
152
153static ssize_t enable_sensor_show(struct device *dev,
154				  struct device_attribute *attr, char *buf)
155{
156	struct hid_sensor_custom *sensor_inst = dev_get_drvdata(dev);
157
158	return sprintf(buf, "%d\n", sensor_inst->enable);
159}
160
161static int set_power_report_state(struct hid_sensor_custom *sensor_inst,
162				  bool state)
163{
164	int power_val = -1;
165	int report_val = -1;
166	u32 power_state_usage_id;
167	u32 report_state_usage_id;
168	int ret;
169
170	/*
171	 * It is possible that the power/report state ids are not present.
172	 * In this case this function will return success. But if the
173	 * ids are present, then it will return error if set fails.
174	 */
175	if (state) {
176		power_state_usage_id =
177			HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM;
178		report_state_usage_id =
179			HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM;
180	} else {
181		power_state_usage_id =
182			HID_USAGE_SENSOR_PROP_POWER_STATE_D4_POWER_OFF_ENUM;
183		report_state_usage_id =
184			HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM;
185	}
186
187	if (sensor_inst->power_state)
188		power_val = hid_sensor_get_usage_index(sensor_inst->hsdev,
189				sensor_inst->power_state->attribute.report_id,
190				sensor_inst->power_state->attribute.index,
191				power_state_usage_id);
192	if (sensor_inst->report_state)
193		report_val = hid_sensor_get_usage_index(sensor_inst->hsdev,
194				sensor_inst->report_state->attribute.report_id,
195				sensor_inst->report_state->attribute.index,
196				report_state_usage_id);
197
198	if (power_val >= 0) {
199		power_val +=
200			sensor_inst->power_state->attribute.logical_minimum;
201		ret = sensor_hub_set_feature(sensor_inst->hsdev,
202				sensor_inst->power_state->attribute.report_id,
203				sensor_inst->power_state->attribute.index,
204				sizeof(power_val),
205				&power_val);
206		if (ret) {
207			hid_err(sensor_inst->hsdev->hdev,
208				"Set power state failed\n");
209			return ret;
210		}
211	}
212
213	if (report_val >= 0) {
214		report_val +=
215			sensor_inst->report_state->attribute.logical_minimum;
216		ret = sensor_hub_set_feature(sensor_inst->hsdev,
217				sensor_inst->report_state->attribute.report_id,
218				sensor_inst->report_state->attribute.index,
219				sizeof(report_val),
220				&report_val);
221		if (ret) {
222			hid_err(sensor_inst->hsdev->hdev,
223				"Set report state failed\n");
224			return ret;
225		}
226	}
227
228	return 0;
229}
230
231static ssize_t enable_sensor_store(struct device *dev,
232				   struct device_attribute *attr,
233				   const char *buf, size_t count)
234{
235	struct hid_sensor_custom *sensor_inst = dev_get_drvdata(dev);
236	int value;
237	int ret = -EINVAL;
238
239	if (kstrtoint(buf, 0, &value) != 0)
240		return -EINVAL;
241
242	mutex_lock(&sensor_inst->mutex);
243	if (value && !sensor_inst->enable) {
244		ret = sensor_hub_device_open(sensor_inst->hsdev);
245		if (ret)
246			goto unlock_state;
247
248		ret = set_power_report_state(sensor_inst, true);
249		if (ret) {
250			sensor_hub_device_close(sensor_inst->hsdev);
251			goto unlock_state;
252		}
253		sensor_inst->enable = true;
254	} else if (!value && sensor_inst->enable) {
255		ret = set_power_report_state(sensor_inst, false);
256		sensor_hub_device_close(sensor_inst->hsdev);
257		sensor_inst->enable = false;
258	}
259unlock_state:
260	mutex_unlock(&sensor_inst->mutex);
261	if (ret < 0)
262		return ret;
263
264	return count;
265}
266static DEVICE_ATTR_RW(enable_sensor);
267
268static struct attribute *enable_sensor_attrs[] = {
269	&dev_attr_enable_sensor.attr,
270	NULL,
271};
272
273static const struct attribute_group enable_sensor_attr_group = {
274	.attrs = enable_sensor_attrs,
275};
276
277static ssize_t show_value(struct device *dev, struct device_attribute *attr,
278			  char *buf)
279{
280	struct hid_sensor_custom *sensor_inst = dev_get_drvdata(dev);
281	struct hid_sensor_hub_attribute_info *attribute;
282	int index, usage, field_index;
283	char name[HID_CUSTOM_NAME_LENGTH];
284	bool feature = false;
285	bool input = false;
286	int value = 0;
287
288	if (sscanf(attr->attr.name, "feature-%x-%x-%s", &index, &usage,
289		   name) == 3) {
290		feature = true;
291		field_index = index + sensor_inst->input_field_count;
292	} else if (sscanf(attr->attr.name, "input-%x-%x-%s", &index, &usage,
293		   name) == 3) {
294		input = true;
295		field_index = index;
296	} else
297		return -EINVAL;
298
299	if (!strncmp(name, "value", strlen("value"))) {
300		u32 report_id;
301		int ret;
302
303		attribute = &sensor_inst->fields[field_index].attribute;
304		report_id = attribute->report_id;
305		if (feature) {
306			u8 values[HID_CUSTOM_MAX_FEATURE_BYTES];
307			int len = 0;
308			u64 value = 0;
309			int i = 0;
310
311			ret = sensor_hub_get_feature(sensor_inst->hsdev,
312						     report_id,
313						     index,
314						     sizeof(values), values);
315			if (ret < 0)
316				return ret;
317
318			while (i < ret) {
319				if (i + attribute->size > ret) {
320					len += scnprintf(&buf[len],
321							PAGE_SIZE - len,
322							"%d ", values[i]);
323					break;
324				}
325				switch (attribute->size) {
326				case 2:
327					value = (u64) *(u16 *)&values[i];
328					i += attribute->size;
329					break;
330				case 4:
331					value = (u64) *(u32 *)&values[i];
332					i += attribute->size;
333					break;
334				case 8:
335					value = *(u64 *)&values[i];
336					i += attribute->size;
337					break;
338				default:
339					value = (u64) values[i];
340					++i;
341					break;
342				}
343				len += scnprintf(&buf[len], PAGE_SIZE - len,
344						"%lld ", value);
345			}
346			len += scnprintf(&buf[len], PAGE_SIZE - len, "\n");
347
348			return len;
349		} else if (input)
350			value = sensor_hub_input_attr_get_raw_value(
351						sensor_inst->hsdev,
352						sensor_inst->hsdev->usage,
353						usage, report_id,
354						SENSOR_HUB_SYNC, false);
355	} else if (!strncmp(name, "units", strlen("units")))
356		value = sensor_inst->fields[field_index].attribute.units;
357	else if (!strncmp(name, "unit-expo", strlen("unit-expo")))
358		value = sensor_inst->fields[field_index].attribute.unit_expo;
359	else if (!strncmp(name, "size", strlen("size")))
360		value = sensor_inst->fields[field_index].attribute.size;
361	else if (!strncmp(name, "minimum", strlen("minimum")))
362		value = sensor_inst->fields[field_index].attribute.
363							logical_minimum;
364	else if (!strncmp(name, "maximum", strlen("maximum")))
365		value = sensor_inst->fields[field_index].attribute.
366							logical_maximum;
367	else if (!strncmp(name, "name", strlen("name"))) {
368		struct hid_custom_usage_desc *usage_desc;
369
370		usage_desc = bsearch(&usage, hid_custom_usage_desc_table,
371				     ARRAY_SIZE(hid_custom_usage_desc_table),
372				     sizeof(struct hid_custom_usage_desc),
373				     usage_id_cmp);
374		if (usage_desc)
375			return snprintf(buf, PAGE_SIZE, "%s\n",
376					usage_desc->desc);
377		else
378			return sprintf(buf, "not-specified\n");
379	 } else
380		return -EINVAL;
381
382	return sprintf(buf, "%d\n", value);
383}
384
385static ssize_t store_value(struct device *dev, struct device_attribute *attr,
386			   const char *buf, size_t count)
387{
388	struct hid_sensor_custom *sensor_inst = dev_get_drvdata(dev);
389	int index, field_index, usage;
390	char name[HID_CUSTOM_NAME_LENGTH];
391	int value, ret;
392
393	if (sscanf(attr->attr.name, "feature-%x-%x-%s", &index, &usage,
394		   name) == 3) {
395		field_index = index + sensor_inst->input_field_count;
396	} else
397		return -EINVAL;
398
399	if (!strncmp(name, "value", strlen("value"))) {
400		u32 report_id;
401
402		if (kstrtoint(buf, 0, &value) != 0)
403			return -EINVAL;
404
405		report_id = sensor_inst->fields[field_index].attribute.
406								report_id;
407		ret = sensor_hub_set_feature(sensor_inst->hsdev, report_id,
408					     index, sizeof(value), &value);
409		if (ret)
410			return ret;
411	} else
412		return -EINVAL;
413
414	return count;
415}
416
417static int hid_sensor_capture_sample(struct hid_sensor_hub_device *hsdev,
418				  unsigned usage_id, size_t raw_len,
419				  char *raw_data, void *priv)
420{
421	struct hid_sensor_custom *sensor_inst = platform_get_drvdata(priv);
422	struct hid_sensor_sample header;
423
424	/* If any error occurs in a sample, rest of the fields are ignored */
425	if (sensor_inst->input_skip_sample) {
426		hid_err(sensor_inst->hsdev->hdev, "Skipped remaining data\n");
427		return 0;
428	}
429
430	hid_dbg(sensor_inst->hsdev->hdev, "%s received %d of %d\n", __func__,
431		(int) (sensor_inst->input_report_recd_size + raw_len),
432		sensor_inst->input_report_size);
433
434	if (!test_bit(0, &sensor_inst->misc_opened))
435		return 0;
436
437	if (!sensor_inst->input_report_recd_size) {
438		int required_size = sizeof(struct hid_sensor_sample) +
439						sensor_inst->input_report_size;
440		header.usage_id = hsdev->usage;
441		header.raw_len = sensor_inst->input_report_size;
442		header.timestamp = ktime_get_real_ns();
443		if (kfifo_avail(&sensor_inst->data_fifo) >= required_size) {
444			kfifo_in(&sensor_inst->data_fifo,
445				 (unsigned char *)&header,
446				 sizeof(header));
447		} else
448			sensor_inst->input_skip_sample = true;
449	}
450	if (kfifo_avail(&sensor_inst->data_fifo) >= raw_len)
451		kfifo_in(&sensor_inst->data_fifo, (unsigned char *)raw_data,
452			 raw_len);
453
454	sensor_inst->input_report_recd_size += raw_len;
455
456	return 0;
457}
458
459static int hid_sensor_send_event(struct hid_sensor_hub_device *hsdev,
460				 unsigned usage_id, void *priv)
461{
462	struct hid_sensor_custom *sensor_inst = platform_get_drvdata(priv);
463
464	if (!test_bit(0, &sensor_inst->misc_opened))
465		return 0;
466
467	sensor_inst->input_report_recd_size = 0;
468	sensor_inst->input_skip_sample = false;
469
470	wake_up(&sensor_inst->wait);
471
472	return 0;
473}
474
475static int hid_sensor_custom_add_field(struct hid_sensor_custom *sensor_inst,
476				       int index, int report_type,
477				       struct hid_report *report,
478				       struct hid_field *field)
479{
480	struct hid_sensor_custom_field *sensor_field;
481	void *fields;
482
483	fields = krealloc(sensor_inst->fields,
484			  (sensor_inst->sensor_field_count + 1) *
485			   sizeof(struct hid_sensor_custom_field), GFP_KERNEL);
486	if (!fields) {
487		kfree(sensor_inst->fields);
488		return -ENOMEM;
489	}
490	sensor_inst->fields = fields;
491	sensor_field = &sensor_inst->fields[sensor_inst->sensor_field_count];
492	sensor_field->attribute.usage_id = sensor_inst->hsdev->usage;
493	if (field->logical)
494		sensor_field->attribute.attrib_id = field->logical;
495	else
496		sensor_field->attribute.attrib_id = field->usage[0].hid;
497
498	sensor_field->attribute.index = index;
499	sensor_field->attribute.report_id = report->id;
500	sensor_field->attribute.units = field->unit;
501	sensor_field->attribute.unit_expo = field->unit_exponent;
502	sensor_field->attribute.size = (field->report_size / 8);
503	sensor_field->attribute.logical_minimum = field->logical_minimum;
504	sensor_field->attribute.logical_maximum = field->logical_maximum;
505
506	if (report_type == HID_FEATURE_REPORT)
507		snprintf(sensor_field->group_name,
508			 sizeof(sensor_field->group_name), "feature-%x-%x",
509			 sensor_field->attribute.index,
510			 sensor_field->attribute.attrib_id);
511	else if (report_type == HID_INPUT_REPORT) {
512		snprintf(sensor_field->group_name,
513			 sizeof(sensor_field->group_name),
514			 "input-%x-%x", sensor_field->attribute.index,
515			 sensor_field->attribute.attrib_id);
516		sensor_inst->input_field_count++;
517		sensor_inst->input_report_size += (field->report_size *
518						   field->report_count) / 8;
519	}
520
521	memset(&sensor_field->hid_custom_attribute_group, 0,
522	       sizeof(struct attribute_group));
523	sensor_inst->sensor_field_count++;
524
525	return 0;
526}
527
528static int hid_sensor_custom_add_fields(struct hid_sensor_custom *sensor_inst,
529					struct hid_report_enum *report_enum,
530					int report_type)
531{
532	int i;
533	int ret;
534	struct hid_report *report;
535	struct hid_field *field;
536	struct hid_sensor_hub_device *hsdev = sensor_inst->hsdev;
537
538	list_for_each_entry(report, &report_enum->report_list, list) {
539		for (i = 0; i < report->maxfield; ++i) {
540			field = report->field[i];
541			if (field->maxusage &&
542			    ((field->usage[0].collection_index >=
543			      hsdev->start_collection_index) &&
544			      (field->usage[0].collection_index <
545			       hsdev->end_collection_index))) {
546
547				ret = hid_sensor_custom_add_field(sensor_inst,
548								  i,
549								  report_type,
550								  report,
551								  field);
552				if (ret)
553					return ret;
554
555			}
556		}
557	}
558
559	return 0;
560}
561
562static int hid_sensor_custom_add_attributes(struct hid_sensor_custom
563								*sensor_inst)
564{
565	struct hid_sensor_hub_device *hsdev = sensor_inst->hsdev;
566	struct hid_device *hdev = hsdev->hdev;
567	int ret = -1;
568	int i, j;
569
570	for (j = 0; j < HID_REPORT_TYPES; ++j) {
571		if (j == HID_OUTPUT_REPORT)
572			continue;
573
574		ret = hid_sensor_custom_add_fields(sensor_inst,
575						   &hdev->report_enum[j], j);
576		if (ret)
577			return ret;
578
579	}
580
581	/* Create sysfs attributes */
582	for (i = 0; i < sensor_inst->sensor_field_count; ++i) {
583		j = 0;
584		while (j < HID_CUSTOM_TOTAL_ATTRS &&
585		       hid_custom_attrs[j].name) {
586			struct device_attribute *device_attr;
587
588			device_attr = &sensor_inst->fields[i].sd_attrs[j];
589
590			snprintf((char *)&sensor_inst->fields[i].attr_name[j],
591				 HID_CUSTOM_NAME_LENGTH, "%s-%s",
592				 sensor_inst->fields[i].group_name,
593				 hid_custom_attrs[j].name);
594			sysfs_attr_init(&device_attr->attr);
595			device_attr->attr.name =
596				(char *)&sensor_inst->fields[i].attr_name[j];
597			device_attr->attr.mode = hid_custom_attrs[j].mode;
598			device_attr->show = show_value;
599			if (hid_custom_attrs[j].mode & S_IWUSR)
600				device_attr->store = store_value;
601			sensor_inst->fields[i].attrs[j] = &device_attr->attr;
602			++j;
603		}
604		sensor_inst->fields[i].attrs[j] = NULL;
605		sensor_inst->fields[i].hid_custom_attribute_group.attrs =
606						sensor_inst->fields[i].attrs;
607		sensor_inst->fields[i].hid_custom_attribute_group.name =
608					sensor_inst->fields[i].group_name;
609		ret = sysfs_create_group(&sensor_inst->pdev->dev.kobj,
610					 &sensor_inst->fields[i].
611					 hid_custom_attribute_group);
612		if (ret)
613			break;
614
615		/* For power or report field store indexes */
616		if (sensor_inst->fields[i].attribute.attrib_id ==
617					HID_USAGE_SENSOR_PROY_POWER_STATE)
618			sensor_inst->power_state = &sensor_inst->fields[i];
619		else if (sensor_inst->fields[i].attribute.attrib_id ==
620					HID_USAGE_SENSOR_PROP_REPORT_STATE)
621			sensor_inst->report_state = &sensor_inst->fields[i];
622	}
623
624	return ret;
625}
626
627static void hid_sensor_custom_remove_attributes(struct hid_sensor_custom *
628								sensor_inst)
629{
630	int i;
631
632	for (i = 0; i < sensor_inst->sensor_field_count; ++i)
633		sysfs_remove_group(&sensor_inst->pdev->dev.kobj,
634				   &sensor_inst->fields[i].
635				   hid_custom_attribute_group);
636
637	kfree(sensor_inst->fields);
638}
639
640static ssize_t hid_sensor_custom_read(struct file *file, char __user *buf,
641				      size_t count, loff_t *f_ps)
642{
643	struct hid_sensor_custom *sensor_inst;
644	unsigned int copied;
645	int ret;
646
647	sensor_inst = container_of(file->private_data,
648				   struct hid_sensor_custom, custom_dev);
649
650	if (count < sizeof(struct hid_sensor_sample))
651		return -EINVAL;
652
653	do {
654		if (kfifo_is_empty(&sensor_inst->data_fifo)) {
655			if (file->f_flags & O_NONBLOCK)
656				return -EAGAIN;
657
658			ret = wait_event_interruptible(sensor_inst->wait,
659				!kfifo_is_empty(&sensor_inst->data_fifo));
660			if (ret)
661				return ret;
662		}
663		ret = kfifo_to_user(&sensor_inst->data_fifo, buf, count,
664				    &copied);
665		if (ret)
666			return ret;
667
668	} while (copied == 0);
669
670	return copied;
671}
672
673static int hid_sensor_custom_release(struct inode *inode, struct file *file)
674{
675	struct hid_sensor_custom *sensor_inst;
676
677	sensor_inst = container_of(file->private_data,
678				   struct hid_sensor_custom, custom_dev);
679
680	clear_bit(0, &sensor_inst->misc_opened);
681
682	return 0;
683}
684
685static int hid_sensor_custom_open(struct inode *inode, struct file *file)
686{
687	struct hid_sensor_custom *sensor_inst;
688
689	sensor_inst = container_of(file->private_data,
690				   struct hid_sensor_custom, custom_dev);
691	/* We essentially have single reader and writer */
692	if (test_and_set_bit(0, &sensor_inst->misc_opened))
693		return -EBUSY;
694
695	return stream_open(inode, file);
696}
697
698static __poll_t hid_sensor_custom_poll(struct file *file,
699					   struct poll_table_struct *wait)
700{
701	struct hid_sensor_custom *sensor_inst;
702	__poll_t mask = 0;
703
704	sensor_inst = container_of(file->private_data,
705				   struct hid_sensor_custom, custom_dev);
706
707	poll_wait(file, &sensor_inst->wait, wait);
708
709	if (!kfifo_is_empty(&sensor_inst->data_fifo))
710		mask = EPOLLIN | EPOLLRDNORM;
711
712	return mask;
713}
714
715static const struct file_operations hid_sensor_custom_fops = {
716	.open =  hid_sensor_custom_open,
717	.read =  hid_sensor_custom_read,
718	.release = hid_sensor_custom_release,
719	.poll = hid_sensor_custom_poll,
720	.llseek = noop_llseek,
721};
722
723static int hid_sensor_custom_dev_if_add(struct hid_sensor_custom *sensor_inst)
724{
725	int ret;
726
727	ret = kfifo_alloc(&sensor_inst->data_fifo, HID_CUSTOM_FIFO_SIZE,
728			  GFP_KERNEL);
729	if (ret)
730		return ret;
731
732	init_waitqueue_head(&sensor_inst->wait);
733
734	sensor_inst->custom_dev.minor = MISC_DYNAMIC_MINOR;
735	sensor_inst->custom_dev.name = dev_name(&sensor_inst->pdev->dev);
736	sensor_inst->custom_dev.fops = &hid_sensor_custom_fops,
737	ret = misc_register(&sensor_inst->custom_dev);
738	if (ret) {
739		kfifo_free(&sensor_inst->data_fifo);
740		return ret;
741	}
742	return 0;
743}
744
745static void hid_sensor_custom_dev_if_remove(struct hid_sensor_custom
746								*sensor_inst)
747{
748	wake_up(&sensor_inst->wait);
749	misc_deregister(&sensor_inst->custom_dev);
750	kfifo_free(&sensor_inst->data_fifo);
751
752}
753
754/*
755 * Match a known custom sensor.
756 * tag and luid is mandatory.
757 */
758struct hid_sensor_custom_match {
759	const char *tag;
760	const char *luid;
761	const char *model;
762	const char *manufacturer;
763	bool check_dmi;
764	struct dmi_system_id dmi;
765};
766
767/*
768 * Custom sensor properties used for matching.
769 */
770struct hid_sensor_custom_properties {
771	u16 serial_num[HID_CUSTOM_MAX_FEATURE_BYTES];
772	u16 model[HID_CUSTOM_MAX_FEATURE_BYTES];
773	u16 manufacturer[HID_CUSTOM_MAX_FEATURE_BYTES];
774};
775
776static const struct hid_sensor_custom_match hid_sensor_custom_known_table[] = {
777	/*
778	 * Intel Integrated Sensor Hub (ISH)
779	 */
780	{	/* Intel ISH hinge */
781		.tag = "INT",
782		.luid = "020B000000000000",
783		.manufacturer = "INTEL",
784	},
785	/*
786	 * Lenovo Intelligent Sensing Solution (LISS)
787	 */
788	{	/* ambient light */
789		.tag = "LISS",
790		.luid = "0041010200000082",
791		.model = "STK3X3X Sensor",
792		.manufacturer = "Vendor 258",
793		.check_dmi = true,
794		.dmi.matches = {
795			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
796		}
797	},
798	{	/* human presence */
799		.tag = "LISS",
800		.luid = "0226000171AC0081",
801		.model = "VL53L1_HOD Sensor",
802		.manufacturer = "ST_MICRO",
803		.check_dmi = true,
804		.dmi.matches = {
805			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
806		}
807	},
808	{}
809};
810
811static bool hid_sensor_custom_prop_match_str(const u16 *prop, const char *match,
812					     size_t count)
813{
814	while (count-- && *prop && *match) {
815		if (*prop != (u16) *match)
816			return false;
817		prop++;
818		match++;
819	}
820
821	return (count == -1) || *prop == (u16)*match;
822}
823
824static int hid_sensor_custom_get_prop(struct hid_sensor_hub_device *hsdev,
825				      u32 prop_usage_id, size_t prop_size,
826				      u16 *prop)
827{
828	struct hid_sensor_hub_attribute_info prop_attr = { 0 };
829	int ret;
830
831	memset(prop, 0, prop_size);
832
833	ret = sensor_hub_input_get_attribute_info(hsdev, HID_FEATURE_REPORT,
834						  hsdev->usage, prop_usage_id,
835						  &prop_attr);
836	if (ret < 0)
837		return ret;
838
839	ret = sensor_hub_get_feature(hsdev, prop_attr.report_id,
840				     prop_attr.index, prop_size, prop);
841	if (ret < 0) {
842		hid_err(hsdev->hdev, "Failed to get sensor property %08x %d\n",
843			prop_usage_id, ret);
844		return ret;
845	}
846
847	return 0;
848}
849
850static bool
851hid_sensor_custom_do_match(struct hid_sensor_hub_device *hsdev,
852			   const struct hid_sensor_custom_match *match,
853			   const struct hid_sensor_custom_properties *prop)
854{
855	struct dmi_system_id dmi[] = { match->dmi, { 0 } };
856
857	if (!hid_sensor_custom_prop_match_str(prop->serial_num, "LUID:", 5) ||
858	    !hid_sensor_custom_prop_match_str(prop->serial_num + 5, match->luid,
859					      HID_CUSTOM_MAX_FEATURE_BYTES - 5))
860		return false;
861
862	if (match->model &&
863	    !hid_sensor_custom_prop_match_str(prop->model, match->model,
864					      HID_CUSTOM_MAX_FEATURE_BYTES))
865		return false;
866
867	if (match->manufacturer &&
868	    !hid_sensor_custom_prop_match_str(prop->manufacturer, match->manufacturer,
869					      HID_CUSTOM_MAX_FEATURE_BYTES))
870		return false;
871
872	if (match->check_dmi && !dmi_check_system(dmi))
873		return false;
874
875	return true;
876}
877
878static int
879hid_sensor_custom_properties_get(struct hid_sensor_hub_device *hsdev,
880				 struct hid_sensor_custom_properties *prop)
881{
882	int ret;
883
884	ret = hid_sensor_custom_get_prop(hsdev,
885					 HID_USAGE_SENSOR_PROP_SERIAL_NUM,
886					 HID_CUSTOM_MAX_FEATURE_BYTES,
887					 prop->serial_num);
888	if (ret < 0)
889		return ret;
890
891	/*
892	 * Ignore errors on the following model and manufacturer properties.
893	 * Because these are optional, it is not an error if they are missing.
894	 */
895
896	hid_sensor_custom_get_prop(hsdev, HID_USAGE_SENSOR_PROP_MODEL,
897				   HID_CUSTOM_MAX_FEATURE_BYTES,
898				   prop->model);
899
900	hid_sensor_custom_get_prop(hsdev, HID_USAGE_SENSOR_PROP_MANUFACTURER,
901				   HID_CUSTOM_MAX_FEATURE_BYTES,
902				   prop->manufacturer);
903
904	return 0;
905}
906
907static int
908hid_sensor_custom_get_known(struct hid_sensor_hub_device *hsdev,
909			    const struct hid_sensor_custom_match **known)
910{
911	int ret;
912	const struct hid_sensor_custom_match *match =
913		hid_sensor_custom_known_table;
914	struct hid_sensor_custom_properties *prop;
915
916	prop = kmalloc(sizeof(struct hid_sensor_custom_properties), GFP_KERNEL);
917	if (!prop)
918		return -ENOMEM;
919
920	ret = hid_sensor_custom_properties_get(hsdev, prop);
921	if (ret < 0)
922		goto out;
923
924	while (match->tag) {
925		if (hid_sensor_custom_do_match(hsdev, match, prop)) {
926			*known = match;
927			ret = 0;
928			goto out;
929		}
930		match++;
931	}
932	ret = -ENODATA;
933out:
934	kfree(prop);
935	return ret;
936}
937
938static struct platform_device *
939hid_sensor_register_platform_device(struct platform_device *pdev,
940				    struct hid_sensor_hub_device *hsdev,
941				    const struct hid_sensor_custom_match *match)
942{
943	char real_usage[HID_SENSOR_USAGE_LENGTH] = { 0 };
944	struct platform_device *custom_pdev;
945	const char *dev_name;
946	char *c;
947
948	memcpy(real_usage, match->luid, 4);
949
950	/* usage id are all lowcase */
951	for (c = real_usage; *c != '\0'; c++)
952		*c = tolower(*c);
953
954	/* HID-SENSOR-TAG-REAL_USAGE_ID */
955	dev_name = kasprintf(GFP_KERNEL, "HID-SENSOR-%s-%s",
956			     match->tag, real_usage);
957	if (!dev_name)
958		return ERR_PTR(-ENOMEM);
959
960	custom_pdev = platform_device_register_data(pdev->dev.parent, dev_name,
961						    PLATFORM_DEVID_AUTO, hsdev,
962						    sizeof(*hsdev));
963	kfree(dev_name);
964	return custom_pdev;
965}
966
967static int hid_sensor_custom_probe(struct platform_device *pdev)
968{
969	struct hid_sensor_custom *sensor_inst;
970	struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
971	int ret;
972	const struct hid_sensor_custom_match *match;
973
974	sensor_inst = devm_kzalloc(&pdev->dev, sizeof(*sensor_inst),
975				   GFP_KERNEL);
976	if (!sensor_inst)
977		return -ENOMEM;
978
979	sensor_inst->callbacks.capture_sample = hid_sensor_capture_sample;
980	sensor_inst->callbacks.send_event = hid_sensor_send_event;
981	sensor_inst->callbacks.pdev = pdev;
982	sensor_inst->hsdev = hsdev;
983	sensor_inst->pdev = pdev;
984	mutex_init(&sensor_inst->mutex);
985	platform_set_drvdata(pdev, sensor_inst);
986
987	ret = hid_sensor_custom_get_known(hsdev, &match);
988	if (!ret) {
989		sensor_inst->custom_pdev =
990			hid_sensor_register_platform_device(pdev, hsdev, match);
991
992		ret = PTR_ERR_OR_ZERO(sensor_inst->custom_pdev);
993		if (ret) {
994			dev_err(&pdev->dev,
995				"register_platform_device failed\n");
996			return ret;
997		}
998
999		return 0;
1000	}
1001
1002	ret = sensor_hub_register_callback(hsdev, hsdev->usage,
1003					   &sensor_inst->callbacks);
1004	if (ret < 0) {
1005		dev_err(&pdev->dev, "callback reg failed\n");
1006		return ret;
1007	}
1008
1009	ret = sysfs_create_group(&sensor_inst->pdev->dev.kobj,
1010				 &enable_sensor_attr_group);
1011	if (ret)
1012		goto err_remove_callback;
1013
1014	ret = hid_sensor_custom_add_attributes(sensor_inst);
1015	if (ret)
1016		goto err_remove_group;
1017
1018	ret = hid_sensor_custom_dev_if_add(sensor_inst);
1019	if (ret)
1020		goto err_remove_attributes;
1021
1022	return 0;
1023
1024err_remove_attributes:
1025	hid_sensor_custom_remove_attributes(sensor_inst);
1026err_remove_group:
1027	sysfs_remove_group(&sensor_inst->pdev->dev.kobj,
1028			   &enable_sensor_attr_group);
1029err_remove_callback:
1030	sensor_hub_remove_callback(hsdev, hsdev->usage);
1031
1032	return ret;
1033}
1034
1035static int hid_sensor_custom_remove(struct platform_device *pdev)
1036{
1037	struct hid_sensor_custom *sensor_inst = platform_get_drvdata(pdev);
1038	struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
1039
1040	if (sensor_inst->custom_pdev) {
1041		platform_device_unregister(sensor_inst->custom_pdev);
1042		return 0;
1043	}
1044
1045	hid_sensor_custom_dev_if_remove(sensor_inst);
1046	hid_sensor_custom_remove_attributes(sensor_inst);
1047	sysfs_remove_group(&sensor_inst->pdev->dev.kobj,
1048			   &enable_sensor_attr_group);
1049	sensor_hub_remove_callback(hsdev, hsdev->usage);
1050
1051	return 0;
1052}
1053
1054static const struct platform_device_id hid_sensor_custom_ids[] = {
1055	{
1056		.name = "HID-SENSOR-2000e1",
1057	},
1058	{
1059		.name = "HID-SENSOR-2000e2",
1060	},
1061	{ /* sentinel */ }
1062};
1063MODULE_DEVICE_TABLE(platform, hid_sensor_custom_ids);
1064
1065static struct platform_driver hid_sensor_custom_platform_driver = {
1066	.id_table = hid_sensor_custom_ids,
1067	.driver = {
1068		.name	= KBUILD_MODNAME,
1069	},
1070	.probe		= hid_sensor_custom_probe,
1071	.remove		= hid_sensor_custom_remove,
1072};
1073module_platform_driver(hid_sensor_custom_platform_driver);
1074
1075MODULE_DESCRIPTION("HID Sensor Custom and Generic sensor Driver");
1076MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
1077MODULE_LICENSE("GPL");
1078