HID: uclogic: Support Gray-coded rotary encoders

Add support for converting Gray-coded rotary encoder input into dial
input compatible with HID standard. Needed for Ugee G5 support.

Signed-off-by: Nikolai Kondrashov <spbnick@gmail.com>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
This commit is contained in:
Nikolai Kondrashov
2019-02-10 12:14:04 +02:00
committed by Benjamin Tissoires
parent fde44ac556
commit 8a47670c35
2 changed files with 37 additions and 0 deletions

View File

@@ -37,6 +37,8 @@ struct uclogic_drvdata {
struct input_dev *pen_input;
/* In-range timer */
struct timer_list inrange_timer;
/* Last rotary encoder state, or U8_MAX for none */
u8 re_state;
};
/**
@@ -175,6 +177,7 @@ static int uclogic_probe(struct hid_device *hdev,
goto failure;
}
timer_setup(&drvdata->inrange_timer, uclogic_inrange_timeout, 0);
drvdata->re_state = U8_MAX;
hid_set_drvdata(hdev, drvdata);
/* Initialize the device and retrieve interface parameters */
@@ -308,6 +311,32 @@ static int uclogic_raw_event(struct hid_device *hdev,
params->frame.dev_id_byte < size) {
data[params->frame.dev_id_byte] = 0xf;
}
/* If need to, and can, read rotary encoder state change */
if (params->frame.re_lsb > 0 &&
params->frame.re_lsb / 8 < size) {
unsigned int byte = params->frame.re_lsb / 8;
unsigned int bit = params->frame.re_lsb % 8;
u8 change;
u8 prev_state = drvdata->re_state;
/* Read Gray-coded state */
u8 state = (data[byte] >> bit) & 0x3;
/* Encode state change into 2-bit signed integer */
if ((prev_state == 1 && state == 0) ||
(prev_state == 2 && state == 3)) {
change = 1;
} else if ((prev_state == 2 && state == 0) ||
(prev_state == 1 && state == 3)) {
change = 3;
} else {
change = 0;
}
/* Write change */
data[byte] = (data[byte] & ~((u8)3 << bit)) |
(change << bit);
/* Remember state */
drvdata->re_state = state;
}
}
return 0;