Lines Matching +full:ten +full:- +full:bit
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 *rsize = drvdata->desc_size; in uclogic_report_fixup()
60 return drvdata->desc_ptr; in uclogic_report_fixup()
93 unsigned long **bit, in uclogic_input_mapping() argument
97 struct uclogic_params *params = &drvdata->params; in uclogic_input_mapping()
99 if (field->application == HID_GD_KEYPAD) { in uclogic_input_mapping()
102 * This only affects previous behavior for devices with more than ten or so buttons. in uclogic_input_mapping()
104 const int key = (usage->hid & HID_USAGE) - 1; in uclogic_input_mapping()
109 bit, in uclogic_input_mapping()
115 } else if (field->application == HID_DG_PEN) { in uclogic_input_mapping()
117 if (params->pen.usage_invalid) in uclogic_input_mapping()
118 return -1; in uclogic_input_mapping()
121 /* Let hid-core decide what to do */ in uclogic_input_mapping()
129 struct uclogic_params *params = &drvdata->params; in uclogic_input_configured()
136 if (!hi->report) in uclogic_input_configured()
143 if (hi->report->id == params->pen.id) { in uclogic_input_configured()
145 drvdata->pen_input = hi->input; in uclogic_input_configured()
149 for (i = 0; i < ARRAY_SIZE(params->frame_list); i++) { in uclogic_input_configured()
150 frame = ¶ms->frame_list[i]; in uclogic_input_configured()
151 if (hi->report->id == frame->id) { in uclogic_input_configured()
153 suffix = frame->suffix; in uclogic_input_configured()
158 if (frame->touch_byte > 0) in uclogic_input_configured()
159 __clear_bit(EV_MSC, hi->input->evbit); in uclogic_input_configured()
164 field = hi->report->field[0]; in uclogic_input_configured()
166 switch (field->application) { in uclogic_input_configured()
190 hi->input->name = devm_kasprintf(&hdev->dev, GFP_KERNEL, in uclogic_input_configured()
191 "%s %s", hdev->name, suffix); in uclogic_input_configured()
192 if (!hi->input->name) in uclogic_input_configured()
193 return -ENOMEM; in uclogic_input_configured()
207 return -EINVAL; in uclogic_probe()
213 hdev->quirks |= HID_QUIRK_MULTI_INPUT; in uclogic_probe()
214 hdev->quirks |= HID_QUIRK_HIDINPUT_FORCE; in uclogic_probe()
217 drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL); in uclogic_probe()
219 rc = -ENOMEM; in uclogic_probe()
222 timer_setup(&drvdata->inrange_timer, uclogic_inrange_timeout, 0); in uclogic_probe()
223 drvdata->re_state = U8_MAX; in uclogic_probe()
224 drvdata->quirks = id->driver_data; in uclogic_probe()
228 rc = uclogic_params_init(&drvdata->params, hdev); in uclogic_probe()
235 uclogic_params_hid_dbg(hdev, &drvdata->params); in uclogic_probe()
236 if (drvdata->params.invalid) { in uclogic_probe()
238 rc = -ENODEV; in uclogic_probe()
243 rc = uclogic_params_get_desc(&drvdata->params, in uclogic_probe()
244 &drvdata->desc_ptr, in uclogic_probe()
245 &drvdata->desc_size); in uclogic_probe()
269 uclogic_params_cleanup(&drvdata->params); in uclogic_probe()
278 /* Re-initialize the device, but discard parameters */ in uclogic_resume()
281 hid_err(hdev, "failed to re-initialize the device\n"); in uclogic_resume()
289 * uclogic_exec_event_hook - if the received event is hooked schedules the
303 if (!p->event_hooks) in uclogic_exec_event_hook()
306 list_for_each_entry(curr, &p->event_hooks->list, list) { in uclogic_exec_event_hook()
307 if (curr->size == size && memcmp(curr->event, event, size) == 0) { in uclogic_exec_event_hook()
308 schedule_work(&curr->work); in uclogic_exec_event_hook()
317 * uclogic_raw_event_pen - handle raw pen events (pen HID reports).
329 struct uclogic_params_pen *pen = &drvdata->params.pen; in uclogic_raw_event_pen()
334 /* If in-range reports are inverted */ in uclogic_raw_event_pen()
335 if (pen->inrange == in uclogic_raw_event_pen()
337 /* Invert the in-range bit */ in uclogic_raw_event_pen()
341 * If report contains fragmented high-resolution pen in uclogic_raw_event_pen()
344 if (size >= 10 && pen->fragmented_hires) { in uclogic_raw_event_pen()
352 * Move Y coord to make space for high-order X in uclogic_raw_event_pen()
357 /* Move high-order X coord byte */ in uclogic_raw_event_pen()
359 /* Move high-order Y coord byte */ in uclogic_raw_event_pen()
365 if (size == 12 && pen->fragmented_hires2) { in uclogic_raw_event_pen()
382 /* If we need to emulate in-range detection */ in uclogic_raw_event_pen()
383 if (pen->inrange == UCLOGIC_PARAMS_PEN_INRANGE_NONE) { in uclogic_raw_event_pen()
384 /* Set in-range bit */ in uclogic_raw_event_pen()
386 /* (Re-)start in-range timeout */ in uclogic_raw_event_pen()
387 mod_timer(&drvdata->inrange_timer, in uclogic_raw_event_pen()
391 if (size >= 12 && pen->tilt_y_flipped) in uclogic_raw_event_pen()
392 data[11] = -data[11]; in uclogic_raw_event_pen()
398 * uclogic_raw_event_frame - handle raw frame events (frame HID reports).
417 if (frame->dev_id_byte > 0 && frame->dev_id_byte < size) { in uclogic_raw_event_frame()
419 if (frame->touch_byte > 0 && frame->touch_byte < size && in uclogic_raw_event_frame()
420 data[frame->touch_byte] == 0) { in uclogic_raw_event_frame()
421 data[frame->dev_id_byte] = 0; in uclogic_raw_event_frame()
423 data[frame->dev_id_byte] = 0xf; in uclogic_raw_event_frame()
428 if (frame->re_lsb > 0 && frame->re_lsb / 8 < size) { in uclogic_raw_event_frame()
429 unsigned int byte = frame->re_lsb / 8; in uclogic_raw_event_frame()
430 unsigned int bit = frame->re_lsb % 8; in uclogic_raw_event_frame() local
433 u8 prev_state = drvdata->re_state; in uclogic_raw_event_frame()
434 /* Read Gray-coded state */ in uclogic_raw_event_frame()
435 u8 state = (data[byte] >> bit) & 0x3; in uclogic_raw_event_frame()
436 /* Encode state change into 2-bit signed integer */ in uclogic_raw_event_frame()
447 data[byte] = (data[byte] & ~((u8)3 << bit)) | in uclogic_raw_event_frame()
448 (change << bit); in uclogic_raw_event_frame()
450 drvdata->re_state = state; in uclogic_raw_event_frame()
454 if (frame->touch_byte > 0 && frame->touch_byte < size) { in uclogic_raw_event_frame()
455 __s8 value = data[frame->touch_byte]; in uclogic_raw_event_frame()
458 if (frame->touch_flip_at != 0) { in uclogic_raw_event_frame()
459 value = frame->touch_flip_at - value; in uclogic_raw_event_frame()
461 value = frame->touch_max + value; in uclogic_raw_event_frame()
463 data[frame->touch_byte] = value - 1; in uclogic_raw_event_frame()
468 if (frame->bitmap_dial_byte > 0 && frame->bitmap_dial_byte < size) { in uclogic_raw_event_frame()
469 switch (data[frame->bitmap_dial_byte]) { in uclogic_raw_event_frame()
471 data[frame->bitmap_dial_byte] = -1; in uclogic_raw_event_frame()
476 data[frame->bitmap_dial_byte] = 0; in uclogic_raw_event_frame()
477 data[frame->bitmap_second_dial_destination_byte] = 1; in uclogic_raw_event_frame()
481 data[frame->bitmap_dial_byte] = 0; in uclogic_raw_event_frame()
482 data[frame->bitmap_second_dial_destination_byte] = -1; in uclogic_raw_event_frame()
494 unsigned int report_id = report->id; in uclogic_raw_event()
496 struct uclogic_params *params = &drvdata->params; in uclogic_raw_event()
502 if (report->type != HID_INPUT_REPORT) in uclogic_raw_event()
510 if ((report_id == params->pen.id) && (size >= 2)) { in uclogic_raw_event()
512 params->pen.subreport_list + in uclogic_raw_event()
513 ARRAY_SIZE(params->pen.subreport_list); in uclogic_raw_event()
515 for (subreport = params->pen.subreport_list; in uclogic_raw_event()
517 if (subreport->value != 0 && in uclogic_raw_event()
518 subreport->value == data[1]) { in uclogic_raw_event()
525 report_id = data[0] = subreport->id; in uclogic_raw_event()
533 for (i = 0; i < ARRAY_SIZE(params->frame_list); i++) { in uclogic_raw_event()
534 if (report_id == params->frame_list[i].id) { in uclogic_raw_event()
536 drvdata, ¶ms->frame_list[i], in uclogic_raw_event()
551 timer_delete_sync(&drvdata->inrange_timer); in uclogic_remove()
553 kfree(drvdata->desc_ptr); in uclogic_remove()
554 uclogic_params_cleanup(&drvdata->params); in uclogic_remove()
646 MODULE_DESCRIPTION("HID driver for UC-Logic devices not fully compliant with HID standard");
648 MODULE_DESCRIPTION("HID driver for UC-Logic devices not fully compliant with HID standard");
651 #include "hid-uclogic-core-test.c"