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

rmi_2d_sensor.c (8615B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (c) 2011-2016 Synaptics Incorporated
      4 * Copyright (c) 2011 Unixphere
      5 */
      6
      7#include <linux/kernel.h>
      8#include <linux/device.h>
      9#include <linux/of.h>
     10#include <linux/input.h>
     11#include <linux/input/mt.h>
     12#include <linux/rmi.h>
     13#include "rmi_driver.h"
     14#include "rmi_2d_sensor.h"
     15
     16#define RMI_2D_REL_POS_MIN		-128
     17#define RMI_2D_REL_POS_MAX		127
     18
     19/* maximum ABS_MT_POSITION displacement (in mm) */
     20#define DMAX 10
     21
     22void rmi_2d_sensor_abs_process(struct rmi_2d_sensor *sensor,
     23				struct rmi_2d_sensor_abs_object *obj,
     24				int slot)
     25{
     26	struct rmi_2d_axis_alignment *axis_align = &sensor->axis_align;
     27
     28	/* we keep the previous values if the finger is released */
     29	if (obj->type == RMI_2D_OBJECT_NONE)
     30		return;
     31
     32	if (axis_align->flip_x)
     33		obj->x = sensor->max_x - obj->x;
     34
     35	if (axis_align->flip_y)
     36		obj->y = sensor->max_y - obj->y;
     37
     38	if (axis_align->swap_axes)
     39		swap(obj->x, obj->y);
     40
     41	/*
     42	 * Here checking if X offset or y offset are specified is
     43	 * redundant. We just add the offsets or clip the values.
     44	 *
     45	 * Note: offsets need to be applied before clipping occurs,
     46	 * or we could get funny values that are outside of
     47	 * clipping boundaries.
     48	 */
     49	obj->x += axis_align->offset_x;
     50	obj->y += axis_align->offset_y;
     51
     52	obj->x =  max(axis_align->clip_x_low, obj->x);
     53	obj->y =  max(axis_align->clip_y_low, obj->y);
     54
     55	if (axis_align->clip_x_high)
     56		obj->x = min(sensor->max_x, obj->x);
     57
     58	if (axis_align->clip_y_high)
     59		obj->y =  min(sensor->max_y, obj->y);
     60
     61	sensor->tracking_pos[slot].x = obj->x;
     62	sensor->tracking_pos[slot].y = obj->y;
     63}
     64EXPORT_SYMBOL_GPL(rmi_2d_sensor_abs_process);
     65
     66void rmi_2d_sensor_abs_report(struct rmi_2d_sensor *sensor,
     67				struct rmi_2d_sensor_abs_object *obj,
     68				int slot)
     69{
     70	struct rmi_2d_axis_alignment *axis_align = &sensor->axis_align;
     71	struct input_dev *input = sensor->input;
     72	int wide, major, minor;
     73
     74	if (sensor->kernel_tracking)
     75		input_mt_slot(input, sensor->tracking_slots[slot]);
     76	else
     77		input_mt_slot(input, slot);
     78
     79	input_mt_report_slot_state(input, obj->mt_tool,
     80				   obj->type != RMI_2D_OBJECT_NONE);
     81
     82	if (obj->type != RMI_2D_OBJECT_NONE) {
     83		obj->x = sensor->tracking_pos[slot].x;
     84		obj->y = sensor->tracking_pos[slot].y;
     85
     86		if (axis_align->swap_axes)
     87			swap(obj->wx, obj->wy);
     88
     89		wide = (obj->wx > obj->wy);
     90		major = max(obj->wx, obj->wy);
     91		minor = min(obj->wx, obj->wy);
     92
     93		if (obj->type == RMI_2D_OBJECT_STYLUS) {
     94			major = max(1, major);
     95			minor = max(1, minor);
     96		}
     97
     98		input_event(sensor->input, EV_ABS, ABS_MT_POSITION_X, obj->x);
     99		input_event(sensor->input, EV_ABS, ABS_MT_POSITION_Y, obj->y);
    100		input_event(sensor->input, EV_ABS, ABS_MT_ORIENTATION, wide);
    101		input_event(sensor->input, EV_ABS, ABS_MT_PRESSURE, obj->z);
    102		input_event(sensor->input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
    103		input_event(sensor->input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
    104
    105		rmi_dbg(RMI_DEBUG_2D_SENSOR, &sensor->input->dev,
    106			"%s: obj[%d]: type: 0x%02x X: %d Y: %d Z: %d WX: %d WY: %d\n",
    107			__func__, slot, obj->type, obj->x, obj->y, obj->z,
    108			obj->wx, obj->wy);
    109	}
    110}
    111EXPORT_SYMBOL_GPL(rmi_2d_sensor_abs_report);
    112
    113void rmi_2d_sensor_rel_report(struct rmi_2d_sensor *sensor, int x, int y)
    114{
    115	struct rmi_2d_axis_alignment *axis_align = &sensor->axis_align;
    116
    117	x = min(RMI_2D_REL_POS_MAX, max(RMI_2D_REL_POS_MIN, (int)x));
    118	y = min(RMI_2D_REL_POS_MAX, max(RMI_2D_REL_POS_MIN, (int)y));
    119
    120	if (axis_align->flip_x)
    121		x = min(RMI_2D_REL_POS_MAX, -x);
    122
    123	if (axis_align->flip_y)
    124		y = min(RMI_2D_REL_POS_MAX, -y);
    125
    126	if (axis_align->swap_axes)
    127		swap(x, y);
    128
    129	if (x || y) {
    130		input_report_rel(sensor->input, REL_X, x);
    131		input_report_rel(sensor->input, REL_Y, y);
    132	}
    133}
    134EXPORT_SYMBOL_GPL(rmi_2d_sensor_rel_report);
    135
    136static void rmi_2d_sensor_set_input_params(struct rmi_2d_sensor *sensor)
    137{
    138	struct input_dev *input = sensor->input;
    139	int res_x;
    140	int res_y;
    141	int max_x, max_y;
    142	int input_flags = 0;
    143
    144	if (sensor->report_abs) {
    145		sensor->min_x = sensor->axis_align.clip_x_low;
    146		if (sensor->axis_align.clip_x_high)
    147			sensor->max_x = min(sensor->max_x,
    148				sensor->axis_align.clip_x_high);
    149
    150		sensor->min_y = sensor->axis_align.clip_y_low;
    151		if (sensor->axis_align.clip_y_high)
    152			sensor->max_y = min(sensor->max_y,
    153				sensor->axis_align.clip_y_high);
    154
    155		set_bit(EV_ABS, input->evbit);
    156
    157		max_x = sensor->max_x;
    158		max_y = sensor->max_y;
    159		if (sensor->axis_align.swap_axes)
    160			swap(max_x, max_y);
    161		input_set_abs_params(input, ABS_MT_POSITION_X, 0, max_x, 0, 0);
    162		input_set_abs_params(input, ABS_MT_POSITION_Y, 0, max_y, 0, 0);
    163
    164		if (sensor->x_mm && sensor->y_mm) {
    165			res_x = (sensor->max_x - sensor->min_x) / sensor->x_mm;
    166			res_y = (sensor->max_y - sensor->min_y) / sensor->y_mm;
    167			if (sensor->axis_align.swap_axes)
    168				swap(res_x, res_y);
    169
    170			input_abs_set_res(input, ABS_X, res_x);
    171			input_abs_set_res(input, ABS_Y, res_y);
    172
    173			input_abs_set_res(input, ABS_MT_POSITION_X, res_x);
    174			input_abs_set_res(input, ABS_MT_POSITION_Y, res_y);
    175
    176			if (!sensor->dmax)
    177				sensor->dmax = DMAX * res_x;
    178		}
    179
    180		input_set_abs_params(input, ABS_MT_PRESSURE, 0, 0xff, 0, 0);
    181		input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 0x0f, 0, 0);
    182		input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 0x0f, 0, 0);
    183		input_set_abs_params(input, ABS_MT_ORIENTATION, 0, 1, 0, 0);
    184		input_set_abs_params(input, ABS_MT_TOOL_TYPE,
    185				     0, MT_TOOL_MAX, 0, 0);
    186
    187		if (sensor->sensor_type == rmi_sensor_touchpad)
    188			input_flags = INPUT_MT_POINTER;
    189		else
    190			input_flags = INPUT_MT_DIRECT;
    191
    192		if (sensor->kernel_tracking)
    193			input_flags |= INPUT_MT_TRACK;
    194
    195		input_mt_init_slots(input, sensor->nbr_fingers, input_flags);
    196	}
    197
    198	if (sensor->report_rel) {
    199		set_bit(EV_REL, input->evbit);
    200		set_bit(REL_X, input->relbit);
    201		set_bit(REL_Y, input->relbit);
    202	}
    203
    204	if (sensor->topbuttonpad)
    205		set_bit(INPUT_PROP_TOPBUTTONPAD, input->propbit);
    206}
    207
    208int rmi_2d_sensor_configure_input(struct rmi_function *fn,
    209					struct rmi_2d_sensor *sensor)
    210{
    211	struct rmi_device *rmi_dev = fn->rmi_dev;
    212	struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev);
    213
    214	if (!drv_data->input)
    215		return -ENODEV;
    216
    217	sensor->input = drv_data->input;
    218	rmi_2d_sensor_set_input_params(sensor);
    219
    220	return 0;
    221}
    222EXPORT_SYMBOL_GPL(rmi_2d_sensor_configure_input);
    223
    224#ifdef CONFIG_OF
    225int rmi_2d_sensor_of_probe(struct device *dev,
    226			struct rmi_2d_sensor_platform_data *pdata)
    227{
    228	int retval;
    229	u32 val;
    230
    231	pdata->axis_align.swap_axes = of_property_read_bool(dev->of_node,
    232						"touchscreen-swapped-x-y");
    233
    234	pdata->axis_align.flip_x = of_property_read_bool(dev->of_node,
    235						"touchscreen-inverted-x");
    236
    237	pdata->axis_align.flip_y = of_property_read_bool(dev->of_node,
    238						"touchscreen-inverted-y");
    239
    240	retval = rmi_of_property_read_u32(dev, &val, "syna,clip-x-low", 1);
    241	if (retval)
    242		return retval;
    243
    244	pdata->axis_align.clip_x_low = val;
    245
    246	retval = rmi_of_property_read_u32(dev, &val, "syna,clip-y-low",	1);
    247	if (retval)
    248		return retval;
    249
    250	pdata->axis_align.clip_y_low = val;
    251
    252	retval = rmi_of_property_read_u32(dev, &val, "syna,clip-x-high", 1);
    253	if (retval)
    254		return retval;
    255
    256	pdata->axis_align.clip_x_high = val;
    257
    258	retval = rmi_of_property_read_u32(dev, &val, "syna,clip-y-high", 1);
    259	if (retval)
    260		return retval;
    261
    262	pdata->axis_align.clip_y_high = val;
    263
    264	retval = rmi_of_property_read_u32(dev, &val, "syna,offset-x", 1);
    265	if (retval)
    266		return retval;
    267
    268	pdata->axis_align.offset_x = val;
    269
    270	retval = rmi_of_property_read_u32(dev, &val, "syna,offset-y", 1);
    271	if (retval)
    272		return retval;
    273
    274	pdata->axis_align.offset_y = val;
    275
    276	retval = rmi_of_property_read_u32(dev, &val, "syna,delta-x-threshold",
    277						1);
    278	if (retval)
    279		return retval;
    280
    281	pdata->axis_align.delta_x_threshold = val;
    282
    283	retval = rmi_of_property_read_u32(dev, &val, "syna,delta-y-threshold",
    284						1);
    285	if (retval)
    286		return retval;
    287
    288	pdata->axis_align.delta_y_threshold = val;
    289
    290	retval = rmi_of_property_read_u32(dev, (u32 *)&pdata->sensor_type,
    291			"syna,sensor-type", 1);
    292	if (retval)
    293		return retval;
    294
    295	retval = rmi_of_property_read_u32(dev, &val, "touchscreen-x-mm", 1);
    296	if (retval)
    297		return retval;
    298
    299	pdata->x_mm = val;
    300
    301	retval = rmi_of_property_read_u32(dev, &val, "touchscreen-y-mm", 1);
    302	if (retval)
    303		return retval;
    304
    305	pdata->y_mm = val;
    306
    307	retval = rmi_of_property_read_u32(dev, &val,
    308				"syna,disable-report-mask", 1);
    309	if (retval)
    310		return retval;
    311
    312	pdata->disable_report_mask = val;
    313
    314	retval = rmi_of_property_read_u32(dev, &val, "syna,rezero-wait-ms",
    315						1);
    316	if (retval)
    317		return retval;
    318
    319	pdata->rezero_wait = val;
    320
    321	return 0;
    322}
    323#else
    324inline int rmi_2d_sensor_of_probe(struct device *dev,
    325			struct rmi_2d_sensor_platform_data *pdata)
    326{
    327	return -ENODEV;
    328}
    329#endif
    330EXPORT_SYMBOL_GPL(rmi_2d_sensor_of_probe);