HID: handle cases of volume knobs generating relative values
There are some devices (for example Dell Multimedia Keyboard SK-8135) that have a volume control knob which generates relative events instead of absolute. hid-input maps them to ABS_VOLUME. HUT pages don't restrict volume to absolute values. Adding REL_VOLUME doesn't seem feasible, nothing knows how to handle it. This patch translates relative ABS_VOLUME events into appropriate number of series of VOLUME_UP or VOLUME_DOWN events respectively, so that userspace sees the correct values in the end. kernel.org bugzilla 5233 Reported-by: Jochen Eisinger <jochen@penguin-breeder.org> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
This commit is contained in:
parent
3c5f4b25f3
commit
2c1d8aea2c
1 changed files with 25 additions and 0 deletions
|
@ -882,6 +882,16 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
||||||
field->dpad = usage->code;
|
field->dpad = usage->code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* for those devices which produce Consumer volume usage as relative,
|
||||||
|
* we emulate pressing volumeup/volumedown appropriate number of times
|
||||||
|
* in hidinput_hid_event()
|
||||||
|
*/
|
||||||
|
if ((usage->type == EV_ABS) && (field->flags & HID_MAIN_ITEM_RELATIVE) &&
|
||||||
|
(usage->code == ABS_VOLUME)) {
|
||||||
|
set_bit(KEY_VOLUMEUP, input->keybit);
|
||||||
|
set_bit(KEY_VOLUMEDOWN, input->keybit);
|
||||||
|
}
|
||||||
|
|
||||||
hid_resolv_event(usage->type, usage->code);
|
hid_resolv_event(usage->type, usage->code);
|
||||||
#ifdef CONFIG_HID_DEBUG
|
#ifdef CONFIG_HID_DEBUG
|
||||||
printk("\n");
|
printk("\n");
|
||||||
|
@ -972,6 +982,21 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
|
||||||
if ((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */
|
if ((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if ((usage->type == EV_ABS) && (field->flags & HID_MAIN_ITEM_RELATIVE) &&
|
||||||
|
(usage->code == ABS_VOLUME)) {
|
||||||
|
int count = abs(value);
|
||||||
|
int direction = value > 0 ? KEY_VOLUMEUP : KEY_VOLUMEDOWN;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
input_event(input, EV_KEY, direction, 1);
|
||||||
|
input_sync(input);
|
||||||
|
input_event(input, EV_KEY, direction, 0);
|
||||||
|
input_sync(input);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
input_event(input, usage->type, usage->code, value);
|
input_event(input, usage->type, usage->code, value);
|
||||||
|
|
||||||
if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY))
|
if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY))
|
||||||
|
|
Loading…
Add table
Reference in a new issue