Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Nikolai Kondrashov and committed by
Benjamin Tissoires
8a47670c fde44ac5

+37
+29
drivers/hid/hid-uclogic-core.c
··· 37 37 struct input_dev *pen_input; 38 38 /* In-range timer */ 39 39 struct timer_list inrange_timer; 40 + /* Last rotary encoder state, or U8_MAX for none */ 41 + u8 re_state; 40 42 }; 41 43 42 44 /** ··· 177 175 goto failure; 178 176 } 179 177 timer_setup(&drvdata->inrange_timer, uclogic_inrange_timeout, 0); 178 + drvdata->re_state = U8_MAX; 180 179 hid_set_drvdata(hdev, drvdata); 181 180 182 181 /* Initialize the device and retrieve interface parameters */ ··· 310 307 if (params->frame.dev_id_byte > 0 && 311 308 params->frame.dev_id_byte < size) { 312 309 data[params->frame.dev_id_byte] = 0xf; 310 + } 311 + /* If need to, and can, read rotary encoder state change */ 312 + if (params->frame.re_lsb > 0 && 313 + params->frame.re_lsb / 8 < size) { 314 + unsigned int byte = params->frame.re_lsb / 8; 315 + unsigned int bit = params->frame.re_lsb % 8; 316 + 317 + u8 change; 318 + u8 prev_state = drvdata->re_state; 319 + /* Read Gray-coded state */ 320 + u8 state = (data[byte] >> bit) & 0x3; 321 + /* Encode state change into 2-bit signed integer */ 322 + if ((prev_state == 1 && state == 0) || 323 + (prev_state == 2 && state == 3)) { 324 + change = 1; 325 + } else if ((prev_state == 2 && state == 0) || 326 + (prev_state == 1 && state == 3)) { 327 + change = 3; 328 + } else { 329 + change = 0; 330 + } 331 + /* Write change */ 332 + data[byte] = (data[byte] & ~((u8)3 << bit)) | 333 + (change << bit); 334 + /* Remember state */ 335 + drvdata->re_state = state; 313 336 } 314 337 } 315 338
+8
drivers/hid/hid-uclogic-params.h
··· 88 88 */ 89 89 unsigned int id; 90 90 /* 91 + * Number of the least-significant bit of the 2-bit state of a rotary 92 + * encoder, in the report. Cannot point to a 2-bit field crossing a 93 + * byte boundary. Zero if not present. Only valid if "id" is not zero. 94 + */ 95 + unsigned int re_lsb; 96 + /* 91 97 * Offset of the Wacom-style device ID byte in the report, to be set 92 98 * to pad device ID (0xf), for compatibility with Wacom drivers. Zero 93 99 * if no changes to the report should be made. Only valid if "id" is ··· 174 168 ".frame.desc_ptr = %p\n" \ 175 169 ".frame.desc_size = %u\n" \ 176 170 ".frame.id = %u\n" \ 171 + ".frame.re_lsb = %u\n" \ 177 172 ".frame.dev_id_byte = %u\n" \ 178 173 ".pen_frame_flag = 0x%02x\n" 179 174 ··· 192 185 (_params)->frame.desc_ptr, \ 193 186 (_params)->frame.desc_size, \ 194 187 (_params)->frame.id, \ 188 + (_params)->frame.re_lsb, \ 195 189 (_params)->frame.dev_id_byte, \ 196 190 (_params)->pen_frame_flag 197 191