Lines Matching +full:rotary +full:- +full:encoder

1 // SPDX-License-Identifier: GPL-2.0+
3 * HID driver for UC-Logic devices not fully compliant with HID standard
5 * Copyright (c) 2010-2014 Nikolai Kondrashov
21 #include "hid-uclogic-params.h"
23 #include "hid-ids.h"
26 * uclogic_inrange_timeout - handle pen in-range state timeout.
37 struct input_dev *input = drvdata->pen_input; in uclogic_inrange_timeout()
43 if (test_bit(BTN_TOUCH, input->key)) { in uclogic_inrange_timeout()
58 if (drvdata->desc_ptr != NULL) { in uclogic_report_fixup()
59 rdesc = drvdata->desc_ptr; in uclogic_report_fixup()
60 *rsize = drvdata->desc_size; in uclogic_report_fixup()
73 struct uclogic_params *params = &drvdata->params; in uclogic_input_mapping()
76 if (params->pen.usage_invalid && (field->application == HID_DG_PEN)) in uclogic_input_mapping()
77 return -1; in uclogic_input_mapping()
79 /* Let hid-core decide what to do */ in uclogic_input_mapping()
87 struct uclogic_params *params = &drvdata->params; in uclogic_input_configured()
94 if (!hi->report) in uclogic_input_configured()
101 if (hi->report->id == params->pen.id) { in uclogic_input_configured()
103 drvdata->pen_input = hi->input; in uclogic_input_configured()
107 for (i = 0; i < ARRAY_SIZE(params->frame_list); i++) { in uclogic_input_configured()
108 frame = &params->frame_list[i]; in uclogic_input_configured()
109 if (hi->report->id == frame->id) { in uclogic_input_configured()
111 suffix = frame->suffix; in uclogic_input_configured()
116 if (frame->touch_byte > 0) in uclogic_input_configured()
117 __clear_bit(EV_MSC, hi->input->evbit); in uclogic_input_configured()
122 field = hi->report->field[0]; in uclogic_input_configured()
124 switch (field->application) { in uclogic_input_configured()
148 hi->input->name = devm_kasprintf(&hdev->dev, GFP_KERNEL, in uclogic_input_configured()
149 "%s %s", hdev->name, suffix); in uclogic_input_configured()
162 return -EINVAL; in uclogic_probe()
168 hdev->quirks |= HID_QUIRK_MULTI_INPUT; in uclogic_probe()
169 hdev->quirks |= HID_QUIRK_HIDINPUT_FORCE; in uclogic_probe()
172 drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL); in uclogic_probe()
174 rc = -ENOMEM; in uclogic_probe()
177 timer_setup(&drvdata->inrange_timer, uclogic_inrange_timeout, 0); in uclogic_probe()
178 drvdata->re_state = U8_MAX; in uclogic_probe()
179 drvdata->quirks = id->driver_data; in uclogic_probe()
183 rc = uclogic_params_init(&drvdata->params, hdev); in uclogic_probe()
190 uclogic_params_hid_dbg(hdev, &drvdata->params); in uclogic_probe()
191 if (drvdata->params.invalid) { in uclogic_probe()
193 rc = -ENODEV; in uclogic_probe()
198 rc = uclogic_params_get_desc(&drvdata->params, in uclogic_probe()
199 &drvdata->desc_ptr, in uclogic_probe()
200 &drvdata->desc_size); in uclogic_probe()
224 uclogic_params_cleanup(&drvdata->params); in uclogic_probe()
234 /* Re-initialize the device, but discard parameters */ in uclogic_resume()
237 hid_err(hdev, "failed to re-initialize the device\n"); in uclogic_resume()
246 * uclogic_exec_event_hook - if the received event is hooked schedules the
260 if (!p->event_hooks) in uclogic_exec_event_hook()
263 list_for_each_entry(curr, &p->event_hooks->list, list) { in uclogic_exec_event_hook()
264 if (curr->size == size && memcmp(curr->event, event, size) == 0) { in uclogic_exec_event_hook()
265 schedule_work(&curr->work); in uclogic_exec_event_hook()
274 * uclogic_raw_event_pen - handle raw pen events (pen HID reports).
286 struct uclogic_params_pen *pen = &drvdata->params.pen; in uclogic_raw_event_pen()
291 /* If in-range reports are inverted */ in uclogic_raw_event_pen()
292 if (pen->inrange == in uclogic_raw_event_pen()
294 /* Invert the in-range bit */ in uclogic_raw_event_pen()
298 * If report contains fragmented high-resolution pen in uclogic_raw_event_pen()
301 if (size >= 10 && pen->fragmented_hires) { in uclogic_raw_event_pen()
309 * Move Y coord to make space for high-order X in uclogic_raw_event_pen()
314 /* Move high-order X coord byte */ in uclogic_raw_event_pen()
316 /* Move high-order Y coord byte */ in uclogic_raw_event_pen()
322 /* If we need to emulate in-range detection */ in uclogic_raw_event_pen()
323 if (pen->inrange == UCLOGIC_PARAMS_PEN_INRANGE_NONE) { in uclogic_raw_event_pen()
324 /* Set in-range bit */ in uclogic_raw_event_pen()
326 /* (Re-)start in-range timeout */ in uclogic_raw_event_pen()
327 mod_timer(&drvdata->inrange_timer, in uclogic_raw_event_pen()
331 if (size >= 12 && pen->tilt_y_flipped) in uclogic_raw_event_pen()
332 data[11] = -data[11]; in uclogic_raw_event_pen()
338 * uclogic_raw_event_frame - handle raw frame events (frame HID reports).
357 if (frame->dev_id_byte > 0 && frame->dev_id_byte < size) { in uclogic_raw_event_frame()
359 if (frame->touch_byte > 0 && frame->touch_byte < size && in uclogic_raw_event_frame()
360 data[frame->touch_byte] == 0) { in uclogic_raw_event_frame()
361 data[frame->dev_id_byte] = 0; in uclogic_raw_event_frame()
363 data[frame->dev_id_byte] = 0xf; in uclogic_raw_event_frame()
367 /* If need to, and can, read rotary encoder state change */ in uclogic_raw_event_frame()
368 if (frame->re_lsb > 0 && frame->re_lsb / 8 < size) { in uclogic_raw_event_frame()
369 unsigned int byte = frame->re_lsb / 8; in uclogic_raw_event_frame()
370 unsigned int bit = frame->re_lsb % 8; in uclogic_raw_event_frame()
373 u8 prev_state = drvdata->re_state; in uclogic_raw_event_frame()
374 /* Read Gray-coded state */ in uclogic_raw_event_frame()
376 /* Encode state change into 2-bit signed integer */ in uclogic_raw_event_frame()
390 drvdata->re_state = state; in uclogic_raw_event_frame()
394 if (frame->touch_byte > 0 && frame->touch_byte < size) { in uclogic_raw_event_frame()
395 __s8 value = data[frame->touch_byte]; in uclogic_raw_event_frame()
398 if (frame->touch_flip_at != 0) { in uclogic_raw_event_frame()
399 value = frame->touch_flip_at - value; in uclogic_raw_event_frame()
401 value = frame->touch_max + value; in uclogic_raw_event_frame()
403 data[frame->touch_byte] = value - 1; in uclogic_raw_event_frame()
408 if (frame->bitmap_dial_byte > 0 && frame->bitmap_dial_byte < size) { in uclogic_raw_event_frame()
409 if (data[frame->bitmap_dial_byte] == 2) in uclogic_raw_event_frame()
410 data[frame->bitmap_dial_byte] = -1; in uclogic_raw_event_frame()
420 unsigned int report_id = report->id; in uclogic_raw_event()
422 struct uclogic_params *params = &drvdata->params; in uclogic_raw_event()
428 if (report->type != HID_INPUT_REPORT) in uclogic_raw_event()
436 if ((report_id == params->pen.id) && (size >= 2)) { in uclogic_raw_event()
438 params->pen.subreport_list + in uclogic_raw_event()
439 ARRAY_SIZE(params->pen.subreport_list); in uclogic_raw_event()
441 for (subreport = params->pen.subreport_list; in uclogic_raw_event()
443 if (subreport->value != 0 && in uclogic_raw_event()
444 subreport->value == data[1]) { in uclogic_raw_event()
451 report_id = data[0] = subreport->id; in uclogic_raw_event()
459 for (i = 0; i < ARRAY_SIZE(params->frame_list); i++) { in uclogic_raw_event()
460 if (report_id == params->frame_list[i].id) { in uclogic_raw_event()
462 drvdata, &params->frame_list[i], in uclogic_raw_event()
477 del_timer_sync(&drvdata->inrange_timer); in uclogic_remove()
479 kfree(drvdata->desc_ptr); in uclogic_remove()
480 uclogic_params_cleanup(&drvdata->params); in uclogic_remove()
573 #include "hid-uclogic-core-test.c"