2019-06-04 10:11:33 +02:00
// SPDX-License-Identifier: GPL-2.0-only
2014-05-28 23:51:53 -07:00
/*
2021-03-22 16:43:00 -07:00
* Generic helper functions for touchscreens and other two - dimensional
* pointing devices
2014-05-28 23:51:53 -07:00
*
* Copyright ( c ) 2014 Sebastian Reichel < sre @ kernel . org >
*/
2015-07-06 15:18:24 -07:00
# include <linux/property.h>
2014-05-28 23:51:53 -07:00
# include <linux/input.h>
2015-03-21 20:17:57 -07:00
# include <linux/input/mt.h>
2014-05-28 23:51:53 -07:00
# include <linux/input/touchscreen.h>
2018-01-10 11:29:23 -08:00
# include <linux/module.h>
2014-05-28 23:51:53 -07:00
2015-07-06 15:18:24 -07:00
static bool touchscreen_get_prop_u32 ( struct device * dev ,
2015-06-01 10:35:16 -07:00
const char * property ,
unsigned int default_value ,
unsigned int * value )
2015-03-21 20:17:48 -07:00
{
2015-06-01 10:35:16 -07:00
u32 val ;
int error ;
2015-03-21 20:17:48 -07:00
2015-07-06 15:18:24 -07:00
error = device_property_read_u32 ( dev , property , & val ) ;
2015-06-01 10:35:16 -07:00
if ( error ) {
* value = default_value ;
return false ;
}
2015-03-21 20:17:48 -07:00
2015-06-01 10:35:16 -07:00
* value = val ;
return true ;
2015-03-21 20:17:48 -07:00
}
static void touchscreen_set_params ( struct input_dev * dev ,
unsigned long axis ,
2018-10-11 17:04:13 -07:00
int min , int max , int fuzz )
2015-03-21 20:17:48 -07:00
{
struct input_absinfo * absinfo ;
if ( ! test_bit ( axis , dev - > absbit ) ) {
2015-07-06 14:45:25 -07:00
dev_warn ( & dev - > dev ,
2021-03-22 16:43:00 -07:00
" Parameters are specified but the axis %lu is not set up \n " ,
2015-07-06 14:45:25 -07:00
axis ) ;
2015-03-21 20:17:48 -07:00
return ;
}
absinfo = & dev - > absinfo [ axis ] ;
2018-10-11 17:04:13 -07:00
absinfo - > minimum = min ;
2015-03-21 20:17:48 -07:00
absinfo - > maximum = max ;
absinfo - > fuzz = fuzz ;
}
2014-05-28 23:51:53 -07:00
/**
2021-03-22 16:43:00 -07:00
* touchscreen_parse_properties - parse common touchscreen properties
2015-07-06 15:18:24 -07:00
* @ input : input device that should be parsed
* @ multitouch : specifies whether parsed properties should be applied to
* single - touch or multi - touch axes
2016-07-15 14:05:29 -07:00
* @ prop : pointer to a struct touchscreen_properties into which to store
* axis swap and invert info for use with touchscreen_report_x_y ( ) ;
* or % NULL
2014-05-28 23:51:53 -07:00
*
2021-03-22 16:43:00 -07:00
* This function parses common properties for touchscreens and sets up the
2015-07-06 15:18:24 -07:00
* input device accordingly . The function keeps previously set up default
2021-03-22 16:43:00 -07:00
* values if no value is specified .
2014-05-28 23:51:53 -07:00
*/
2016-07-15 14:05:29 -07:00
void touchscreen_parse_properties ( struct input_dev * input , bool multitouch ,
struct touchscreen_properties * prop )
2014-05-28 23:51:53 -07:00
{
2015-07-06 15:18:24 -07:00
struct device * dev = input - > dev . parent ;
2018-10-11 17:04:13 -07:00
struct input_absinfo * absinfo ;
2020-03-06 17:11:46 -08:00
unsigned int axis , axis_x , axis_y ;
2018-10-11 17:04:13 -07:00
unsigned int minimum , maximum , fuzz ;
2015-06-01 10:35:16 -07:00
bool data_present ;
2014-05-28 23:51:53 -07:00
2015-07-06 15:18:24 -07:00
input_alloc_absinfo ( input ) ;
if ( ! input - > absinfo )
2014-05-28 23:51:53 -07:00
return ;
2020-03-06 17:11:46 -08:00
axis_x = multitouch ? ABS_MT_POSITION_X : ABS_X ;
axis_y = multitouch ? ABS_MT_POSITION_Y : ABS_Y ;
2018-10-11 17:04:13 -07:00
data_present = touchscreen_get_prop_u32 ( dev , " touchscreen-min-x " ,
2020-03-06 17:11:46 -08:00
input_abs_get_min ( input , axis_x ) ,
2018-10-11 17:04:13 -07:00
& minimum ) |
touchscreen_get_prop_u32 ( dev , " touchscreen-size-x " ,
2015-07-06 15:18:24 -07:00
input_abs_get_max ( input ,
2020-03-06 17:11:46 -08:00
axis_x ) + 1 ,
2015-06-01 10:35:16 -07:00
& maximum ) |
2015-07-06 15:18:24 -07:00
touchscreen_get_prop_u32 ( dev , " touchscreen-fuzz-x " ,
2020-03-06 17:11:46 -08:00
input_abs_get_fuzz ( input , axis_x ) ,
2015-06-01 10:35:16 -07:00
& fuzz ) ;
if ( data_present )
2020-03-06 17:11:46 -08:00
touchscreen_set_params ( input , axis_x , minimum , maximum - 1 , fuzz ) ;
2014-05-28 23:51:53 -07:00
2018-10-11 17:04:13 -07:00
data_present = touchscreen_get_prop_u32 ( dev , " touchscreen-min-y " ,
2020-03-06 17:11:46 -08:00
input_abs_get_min ( input , axis_y ) ,
2018-10-11 17:04:13 -07:00
& minimum ) |
touchscreen_get_prop_u32 ( dev , " touchscreen-size-y " ,
2015-07-06 15:18:24 -07:00
input_abs_get_max ( input ,
2020-03-06 17:11:46 -08:00
axis_y ) + 1 ,
2015-06-01 10:35:16 -07:00
& maximum ) |
2015-07-06 15:18:24 -07:00
touchscreen_get_prop_u32 ( dev , " touchscreen-fuzz-y " ,
2020-03-06 17:11:46 -08:00
input_abs_get_fuzz ( input , axis_y ) ,
2015-06-01 10:35:16 -07:00
& fuzz ) ;
if ( data_present )
2020-03-06 17:11:46 -08:00
touchscreen_set_params ( input , axis_y , minimum , maximum - 1 , fuzz ) ;
2014-05-28 23:51:53 -07:00
2015-06-01 10:35:16 -07:00
axis = multitouch ? ABS_MT_PRESSURE : ABS_PRESSURE ;
2015-07-06 15:18:24 -07:00
data_present = touchscreen_get_prop_u32 ( dev ,
" touchscreen-max-pressure " ,
input_abs_get_max ( input , axis ) ,
2015-06-01 10:35:16 -07:00
& maximum ) |
2015-07-06 15:18:24 -07:00
touchscreen_get_prop_u32 ( dev ,
" touchscreen-fuzz-pressure " ,
input_abs_get_fuzz ( input , axis ) ,
2015-06-01 10:35:16 -07:00
& fuzz ) ;
if ( data_present )
2018-10-11 17:04:13 -07:00
touchscreen_set_params ( input , axis , 0 , maximum , fuzz ) ;
2016-07-15 14:05:29 -07:00
if ( ! prop )
return ;
2020-03-06 17:11:46 -08:00
prop - > max_x = input_abs_get_max ( input , axis_x ) ;
prop - > max_y = input_abs_get_max ( input , axis_y ) ;
2018-10-11 17:04:13 -07:00
2016-07-15 14:05:29 -07:00
prop - > invert_x =
device_property_read_bool ( dev , " touchscreen-inverted-x " ) ;
2018-10-11 17:04:13 -07:00
if ( prop - > invert_x ) {
2020-03-06 17:11:46 -08:00
absinfo = & input - > absinfo [ axis_x ] ;
2018-10-11 17:04:13 -07:00
absinfo - > maximum - = absinfo - > minimum ;
absinfo - > minimum = 0 ;
}
2016-07-15 14:05:29 -07:00
prop - > invert_y =
device_property_read_bool ( dev , " touchscreen-inverted-y " ) ;
2018-10-11 17:04:13 -07:00
if ( prop - > invert_y ) {
2020-03-06 17:11:46 -08:00
absinfo = & input - > absinfo [ axis_y ] ;
2018-10-11 17:04:13 -07:00
absinfo - > maximum - = absinfo - > minimum ;
absinfo - > minimum = 0 ;
}
2016-07-15 14:05:29 -07:00
prop - > swap_x_y =
device_property_read_bool ( dev , " touchscreen-swapped-x-y " ) ;
if ( prop - > swap_x_y )
2020-03-06 17:11:46 -08:00
swap ( input - > absinfo [ axis_x ] , input - > absinfo [ axis_y ] ) ;
2014-05-28 23:51:53 -07:00
}
2015-07-06 15:18:24 -07:00
EXPORT_SYMBOL ( touchscreen_parse_properties ) ;
2016-07-15 14:05:29 -07:00
static void
touchscreen_apply_prop_to_x_y ( const struct touchscreen_properties * prop ,
unsigned int * x , unsigned int * y )
{
if ( prop - > invert_x )
* x = prop - > max_x - * x ;
if ( prop - > invert_y )
* y = prop - > max_y - * y ;
if ( prop - > swap_x_y )
swap ( * x , * y ) ;
}
/**
* touchscreen_set_mt_pos - Set input_mt_pos coordinates
* @ pos : input_mt_pos to set coordinates of
* @ prop : pointer to a struct touchscreen_properties
* @ x : X coordinate to store in pos
* @ y : Y coordinate to store in pos
*
* Adjust the passed in x and y values applying any axis inversion and
* swapping requested in the passed in touchscreen_properties and store
* the result in a struct input_mt_pos .
*/
void touchscreen_set_mt_pos ( struct input_mt_pos * pos ,
const struct touchscreen_properties * prop ,
unsigned int x , unsigned int y )
{
touchscreen_apply_prop_to_x_y ( prop , & x , & y ) ;
pos - > x = x ;
pos - > y = y ;
}
EXPORT_SYMBOL ( touchscreen_set_mt_pos ) ;
/**
* touchscreen_report_pos - Report touchscreen coordinates
* @ input : input_device to report coordinates for
* @ prop : pointer to a struct touchscreen_properties
* @ x : X coordinate to report
* @ y : Y coordinate to report
* @ multitouch : Report coordinates on single - touch or multi - touch axes
*
* Adjust the passed in x and y values applying any axis inversion and
* swapping requested in the passed in touchscreen_properties and then
* report the resulting coordinates on the input_dev ' s x and y axis .
*/
void touchscreen_report_pos ( struct input_dev * input ,
const struct touchscreen_properties * prop ,
unsigned int x , unsigned int y ,
bool multitouch )
{
touchscreen_apply_prop_to_x_y ( prop , & x , & y ) ;
input_report_abs ( input , multitouch ? ABS_MT_POSITION_X : ABS_X , x ) ;
input_report_abs ( input , multitouch ? ABS_MT_POSITION_Y : ABS_Y , y ) ;
}
EXPORT_SYMBOL ( touchscreen_report_pos ) ;
2018-01-10 11:29:23 -08:00
MODULE_LICENSE ( " GPL v2 " ) ;
2021-03-22 16:43:00 -07:00
MODULE_DESCRIPTION ( " Helper functions for touchscreens and other devices " ) ;