Input: ad714x - fix captouch wheel option algorithm
As reported by Jean-Francois Dagenais, the wheel algorithm caused a divide by zero exception due to missing variable pre-initialization. In fact it turned out that the whole algorithm had several problems. It is therefore replaced with something that is known working. Signed-off-by: Michael Hennerich <michael.hennerich@analog.com> Tested-by: Jean-Francois Dagenais <jeff.dagenais@gmail.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
This commit is contained in:
parent
3532cb0ca2
commit
f1e430e636
@ -79,13 +79,7 @@ struct ad714x_slider_drv {
|
|||||||
struct ad714x_wheel_drv {
|
struct ad714x_wheel_drv {
|
||||||
int abs_pos;
|
int abs_pos;
|
||||||
int flt_pos;
|
int flt_pos;
|
||||||
int pre_mean_value;
|
|
||||||
int pre_highest_stage;
|
int pre_highest_stage;
|
||||||
int pre_mean_value_no_offset;
|
|
||||||
int mean_value;
|
|
||||||
int mean_value_no_offset;
|
|
||||||
int pos_offset;
|
|
||||||
int pos_ratio;
|
|
||||||
int highest_stage;
|
int highest_stage;
|
||||||
enum ad714x_device_state state;
|
enum ad714x_device_state state;
|
||||||
struct input_dev *input;
|
struct input_dev *input;
|
||||||
@ -404,7 +398,6 @@ static void ad714x_slider_state_machine(struct ad714x_chip *ad714x, int idx)
|
|||||||
ad714x_slider_cal_highest_stage(ad714x, idx);
|
ad714x_slider_cal_highest_stage(ad714x, idx);
|
||||||
ad714x_slider_cal_abs_pos(ad714x, idx);
|
ad714x_slider_cal_abs_pos(ad714x, idx);
|
||||||
ad714x_slider_cal_flt_pos(ad714x, idx);
|
ad714x_slider_cal_flt_pos(ad714x, idx);
|
||||||
|
|
||||||
input_report_abs(sw->input, ABS_X, sw->flt_pos);
|
input_report_abs(sw->input, ABS_X, sw->flt_pos);
|
||||||
input_report_key(sw->input, BTN_TOUCH, 1);
|
input_report_key(sw->input, BTN_TOUCH, 1);
|
||||||
} else {
|
} else {
|
||||||
@ -468,104 +461,41 @@ static void ad714x_wheel_cal_sensor_val(struct ad714x_chip *ad714x, int idx)
|
|||||||
/*
|
/*
|
||||||
* When the scroll wheel is activated, we compute the absolute position based
|
* When the scroll wheel is activated, we compute the absolute position based
|
||||||
* on the sensor values. To calculate the position, we first determine the
|
* on the sensor values. To calculate the position, we first determine the
|
||||||
* sensor that has the greatest response among the 8 sensors that constitutes
|
* sensor that has the greatest response among the sensors that constitutes
|
||||||
* the scrollwheel. Then we determined the 2 sensors on either sides of the
|
* the scrollwheel. Then we determined the sensors on either sides of the
|
||||||
* sensor with the highest response and we apply weights to these sensors. The
|
* sensor with the highest response and we apply weights to these sensors. The
|
||||||
* result of this computation gives us the mean value which defined by the
|
* result of this computation gives us the mean value.
|
||||||
* following formula:
|
|
||||||
* For i= second_before_highest_stage to i= second_after_highest_stage
|
|
||||||
* v += Sensor response(i)*WEIGHT*(i+3)
|
|
||||||
* w += Sensor response(i)
|
|
||||||
* Mean_Value=v/w
|
|
||||||
* pos_on_scrollwheel = (Mean_Value - position_offset) / position_ratio
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define WEIGHT_FACTOR 30
|
|
||||||
/* This constant prevents the "PositionOffset" from reaching a big value */
|
|
||||||
#define OFFSET_POSITION_CLAMP 120
|
|
||||||
static void ad714x_wheel_cal_abs_pos(struct ad714x_chip *ad714x, int idx)
|
static void ad714x_wheel_cal_abs_pos(struct ad714x_chip *ad714x, int idx)
|
||||||
{
|
{
|
||||||
struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx];
|
struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx];
|
||||||
struct ad714x_wheel_drv *sw = &ad714x->sw->wheel[idx];
|
struct ad714x_wheel_drv *sw = &ad714x->sw->wheel[idx];
|
||||||
int stage_num = hw->end_stage - hw->start_stage + 1;
|
int stage_num = hw->end_stage - hw->start_stage + 1;
|
||||||
int second_before, first_before, highest, first_after, second_after;
|
int first_before, highest, first_after;
|
||||||
int a_param, b_param;
|
int a_param, b_param;
|
||||||
|
|
||||||
/* Calculate Mean value */
|
|
||||||
|
|
||||||
second_before = (sw->highest_stage + stage_num - 2) % stage_num;
|
|
||||||
first_before = (sw->highest_stage + stage_num - 1) % stage_num;
|
first_before = (sw->highest_stage + stage_num - 1) % stage_num;
|
||||||
highest = sw->highest_stage;
|
highest = sw->highest_stage;
|
||||||
first_after = (sw->highest_stage + stage_num + 1) % stage_num;
|
first_after = (sw->highest_stage + stage_num + 1) % stage_num;
|
||||||
second_after = (sw->highest_stage + stage_num + 2) % stage_num;
|
|
||||||
|
|
||||||
if (((sw->highest_stage - hw->start_stage) > 1) &&
|
a_param = ad714x->sensor_val[highest] *
|
||||||
((hw->end_stage - sw->highest_stage) > 1)) {
|
(highest - hw->start_stage) +
|
||||||
a_param = ad714x->sensor_val[second_before] *
|
|
||||||
(second_before - hw->start_stage + 3) +
|
|
||||||
ad714x->sensor_val[first_before] *
|
ad714x->sensor_val[first_before] *
|
||||||
(second_before - hw->start_stage + 3) +
|
(highest - hw->start_stage - 1) +
|
||||||
ad714x->sensor_val[highest] *
|
|
||||||
(second_before - hw->start_stage + 3) +
|
|
||||||
ad714x->sensor_val[first_after] *
|
ad714x->sensor_val[first_after] *
|
||||||
(first_after - hw->start_stage + 3) +
|
(highest - hw->start_stage + 1);
|
||||||
ad714x->sensor_val[second_after] *
|
b_param = ad714x->sensor_val[highest] +
|
||||||
(second_after - hw->start_stage + 3);
|
|
||||||
} else {
|
|
||||||
a_param = ad714x->sensor_val[second_before] *
|
|
||||||
(second_before - hw->start_stage + 1) +
|
|
||||||
ad714x->sensor_val[first_before] *
|
|
||||||
(second_before - hw->start_stage + 2) +
|
|
||||||
ad714x->sensor_val[highest] *
|
|
||||||
(second_before - hw->start_stage + 3) +
|
|
||||||
ad714x->sensor_val[first_after] *
|
|
||||||
(first_after - hw->start_stage + 4) +
|
|
||||||
ad714x->sensor_val[second_after] *
|
|
||||||
(second_after - hw->start_stage + 5);
|
|
||||||
}
|
|
||||||
a_param *= WEIGHT_FACTOR;
|
|
||||||
|
|
||||||
b_param = ad714x->sensor_val[second_before] +
|
|
||||||
ad714x->sensor_val[first_before] +
|
ad714x->sensor_val[first_before] +
|
||||||
ad714x->sensor_val[highest] +
|
ad714x->sensor_val[first_after];
|
||||||
ad714x->sensor_val[first_after] +
|
|
||||||
ad714x->sensor_val[second_after];
|
|
||||||
|
|
||||||
sw->pre_mean_value = sw->mean_value;
|
sw->abs_pos = ((hw->max_coord / (hw->end_stage - hw->start_stage)) *
|
||||||
sw->mean_value = a_param / b_param;
|
a_param) / b_param;
|
||||||
|
|
||||||
/* Calculate the offset */
|
|
||||||
|
|
||||||
if ((sw->pre_highest_stage == hw->end_stage) &&
|
|
||||||
(sw->highest_stage == hw->start_stage))
|
|
||||||
sw->pos_offset = sw->mean_value;
|
|
||||||
else if ((sw->pre_highest_stage == hw->start_stage) &&
|
|
||||||
(sw->highest_stage == hw->end_stage))
|
|
||||||
sw->pos_offset = sw->pre_mean_value;
|
|
||||||
|
|
||||||
if (sw->pos_offset > OFFSET_POSITION_CLAMP)
|
|
||||||
sw->pos_offset = OFFSET_POSITION_CLAMP;
|
|
||||||
|
|
||||||
/* Calculate the mean value without the offset */
|
|
||||||
|
|
||||||
sw->pre_mean_value_no_offset = sw->mean_value_no_offset;
|
|
||||||
sw->mean_value_no_offset = sw->mean_value - sw->pos_offset;
|
|
||||||
if (sw->mean_value_no_offset < 0)
|
|
||||||
sw->mean_value_no_offset = 0;
|
|
||||||
|
|
||||||
/* Calculate ratio to scale down to NUMBER_OF_WANTED_POSITIONS */
|
|
||||||
|
|
||||||
if ((sw->pre_highest_stage == hw->end_stage) &&
|
|
||||||
(sw->highest_stage == hw->start_stage))
|
|
||||||
sw->pos_ratio = (sw->pre_mean_value_no_offset * 100) /
|
|
||||||
hw->max_coord;
|
|
||||||
else if ((sw->pre_highest_stage == hw->start_stage) &&
|
|
||||||
(sw->highest_stage == hw->end_stage))
|
|
||||||
sw->pos_ratio = (sw->mean_value_no_offset * 100) /
|
|
||||||
hw->max_coord;
|
|
||||||
sw->abs_pos = (sw->mean_value_no_offset * 100) / sw->pos_ratio;
|
|
||||||
if (sw->abs_pos > hw->max_coord)
|
if (sw->abs_pos > hw->max_coord)
|
||||||
sw->abs_pos = hw->max_coord;
|
sw->abs_pos = hw->max_coord;
|
||||||
|
else if (sw->abs_pos < 0)
|
||||||
|
sw->abs_pos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ad714x_wheel_cal_flt_pos(struct ad714x_chip *ad714x, int idx)
|
static void ad714x_wheel_cal_flt_pos(struct ad714x_chip *ad714x, int idx)
|
||||||
@ -639,9 +569,8 @@ static void ad714x_wheel_state_machine(struct ad714x_chip *ad714x, int idx)
|
|||||||
ad714x_wheel_cal_highest_stage(ad714x, idx);
|
ad714x_wheel_cal_highest_stage(ad714x, idx);
|
||||||
ad714x_wheel_cal_abs_pos(ad714x, idx);
|
ad714x_wheel_cal_abs_pos(ad714x, idx);
|
||||||
ad714x_wheel_cal_flt_pos(ad714x, idx);
|
ad714x_wheel_cal_flt_pos(ad714x, idx);
|
||||||
|
|
||||||
input_report_abs(sw->input, ABS_WHEEL,
|
input_report_abs(sw->input, ABS_WHEEL,
|
||||||
sw->abs_pos);
|
sw->flt_pos);
|
||||||
input_report_key(sw->input, BTN_TOUCH, 1);
|
input_report_key(sw->input, BTN_TOUCH, 1);
|
||||||
} else {
|
} else {
|
||||||
/* When the user lifts off the sensor, configure
|
/* When the user lifts off the sensor, configure
|
||||||
|
Loading…
Reference in New Issue
Block a user