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:
parent
fde44ac556
commit
8a47670c35
|
@ -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;
|
||||
|
|
|
@ -87,6 +87,12 @@ struct uclogic_params_frame {
|
|||
* Report ID, if reports should be tweaked, zero if not.
|
||||
*/
|
||||
unsigned int id;
|
||||
/*
|
||||
* Number of the least-significant bit of the 2-bit state of a rotary
|
||||
* encoder, in the report. Cannot point to a 2-bit field crossing a
|
||||
* byte boundary. Zero if not present. Only valid if "id" is not zero.
|
||||
*/
|
||||
unsigned int re_lsb;
|
||||
/*
|
||||
* Offset of the Wacom-style device ID byte in the report, to be set
|
||||
* to pad device ID (0xf), for compatibility with Wacom drivers. Zero
|
||||
|
@ -168,6 +174,7 @@ extern int uclogic_params_init(struct uclogic_params *params,
|
|||
".frame.desc_ptr = %p\n" \
|
||||
".frame.desc_size = %u\n" \
|
||||
".frame.id = %u\n" \
|
||||
".frame.re_lsb = %u\n" \
|
||||
".frame.dev_id_byte = %u\n" \
|
||||
".pen_frame_flag = 0x%02x\n"
|
||||
|
||||
|
@ -185,6 +192,7 @@ extern int uclogic_params_init(struct uclogic_params *params,
|
|||
(_params)->frame.desc_ptr, \
|
||||
(_params)->frame.desc_size, \
|
||||
(_params)->frame.id, \
|
||||
(_params)->frame.re_lsb, \
|
||||
(_params)->frame.dev_id_byte, \
|
||||
(_params)->pen_frame_flag
|
||||
|
||||
|
|
Loading…
Reference in a new issue