diff options
author | Hans de Goede <hdegoede@redhat.com> | 2014-01-29 11:57:43 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2014-02-03 05:11:53 -0500 |
commit | 3faed1aff786a007b3ea0549ac469e09f48c98f9 (patch) | |
tree | ebeb9fddb3a4bd2a2544a8ad5c9a03b3891abdcb /drivers/hid/hid-microsoft.c | |
parent | aac59f6a96044f423408ee17f4e8e11d904c2b80 (diff) |
HID: hid-microsoft: Add support for scrollwheel and special keypad keys
The Microsoft Office keyboard has a scrollwheel as well as some special keys
above the keypad which are handled through the custom MS usage page, this
commit adds support for these.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-microsoft.c')
-rw-r--r-- | drivers/hid/hid-microsoft.c | 49 |
1 files changed, 48 insertions, 1 deletions
diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index 5268dec5d81a..fe415e8ed7c4 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c | |||
@@ -68,6 +68,26 @@ static int ms_ergonomy_kb_quirk(struct hid_input *hi, struct hid_usage *usage, | |||
68 | switch (usage->hid & HID_USAGE) { | 68 | switch (usage->hid & HID_USAGE) { |
69 | case 0xfd06: ms_map_key_clear(KEY_CHAT); break; | 69 | case 0xfd06: ms_map_key_clear(KEY_CHAT); break; |
70 | case 0xfd07: ms_map_key_clear(KEY_PHONE); break; | 70 | case 0xfd07: ms_map_key_clear(KEY_PHONE); break; |
71 | case 0xff00: | ||
72 | /* Special keypad keys */ | ||
73 | ms_map_key_clear(KEY_KPEQUAL); | ||
74 | set_bit(KEY_KPLEFTPAREN, input->keybit); | ||
75 | set_bit(KEY_KPRIGHTPAREN, input->keybit); | ||
76 | break; | ||
77 | case 0xff01: | ||
78 | /* Scroll wheel */ | ||
79 | hid_map_usage_clear(hi, usage, bit, max, EV_REL, REL_WHEEL); | ||
80 | break; | ||
81 | case 0xff02: | ||
82 | /* | ||
83 | * This byte contains a copy of the modifier keys byte of a | ||
84 | * standard hid keyboard report, as send by interface 0 | ||
85 | * (this usage is found on interface 1). | ||
86 | * | ||
87 | * This byte only gets send when another key in the same report | ||
88 | * changes state, and as such is useless, ignore it. | ||
89 | */ | ||
90 | return -1; | ||
71 | case 0xff05: | 91 | case 0xff05: |
72 | set_bit(EV_REP, input->evbit); | 92 | set_bit(EV_REP, input->evbit); |
73 | ms_map_key_clear(KEY_F13); | 93 | ms_map_key_clear(KEY_F13); |
@@ -137,14 +157,39 @@ static int ms_event(struct hid_device *hdev, struct hid_field *field, | |||
137 | struct hid_usage *usage, __s32 value) | 157 | struct hid_usage *usage, __s32 value) |
138 | { | 158 | { |
139 | unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); | 159 | unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); |
160 | struct input_dev *input; | ||
140 | 161 | ||
141 | if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput || | 162 | if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput || |
142 | !usage->type) | 163 | !usage->type) |
143 | return 0; | 164 | return 0; |
144 | 165 | ||
166 | input = field->hidinput->input; | ||
167 | |||
145 | /* Handling MS keyboards special buttons */ | 168 | /* Handling MS keyboards special buttons */ |
169 | if (quirks & MS_ERGONOMY && usage->hid == (HID_UP_MSVENDOR | 0xff00)) { | ||
170 | /* Special keypad keys */ | ||
171 | input_report_key(input, KEY_KPEQUAL, value & 0x01); | ||
172 | input_report_key(input, KEY_KPLEFTPAREN, value & 0x02); | ||
173 | input_report_key(input, KEY_KPRIGHTPAREN, value & 0x04); | ||
174 | return 1; | ||
175 | } | ||
176 | |||
177 | if (quirks & MS_ERGONOMY && usage->hid == (HID_UP_MSVENDOR | 0xff01)) { | ||
178 | /* Scroll wheel */ | ||
179 | int step = ((value & 0x60) >> 5) + 1; | ||
180 | |||
181 | switch (value & 0x1f) { | ||
182 | case 0x01: | ||
183 | input_report_rel(input, REL_WHEEL, step); | ||
184 | break; | ||
185 | case 0x1f: | ||
186 | input_report_rel(input, REL_WHEEL, -step); | ||
187 | break; | ||
188 | } | ||
189 | return 1; | ||
190 | } | ||
191 | |||
146 | if (quirks & MS_ERGONOMY && usage->hid == (HID_UP_MSVENDOR | 0xff05)) { | 192 | if (quirks & MS_ERGONOMY && usage->hid == (HID_UP_MSVENDOR | 0xff05)) { |
147 | struct input_dev *input = field->hidinput->input; | ||
148 | static unsigned int last_key = 0; | 193 | static unsigned int last_key = 0; |
149 | unsigned int key = 0; | 194 | unsigned int key = 0; |
150 | switch (value) { | 195 | switch (value) { |
@@ -197,6 +242,8 @@ err_free: | |||
197 | static const struct hid_device_id ms_devices[] = { | 242 | static const struct hid_device_id ms_devices[] = { |
198 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV), | 243 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV), |
199 | .driver_data = MS_HIDINPUT }, | 244 | .driver_data = MS_HIDINPUT }, |
245 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB), | ||
246 | .driver_data = MS_ERGONOMY }, | ||
200 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K), | 247 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K), |
201 | .driver_data = MS_ERGONOMY }, | 248 | .driver_data = MS_ERGONOMY }, |
202 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K_JP), | 249 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K_JP), |