xref: /openbmc/linux/drivers/hid/hid-lg.c (revision 66d61bec)
1 /*
2  *  HID driver for some logitech "special" devices
3  *
4  *  Copyright (c) 1999 Andreas Gal
5  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
6  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
7  *  Copyright (c) 2006-2007 Jiri Kosina
8  *  Copyright (c) 2007 Paul Walmsley
9  *  Copyright (c) 2008 Jiri Slaby
10  */
11 
12 /*
13  * This program is free software; you can redistribute it and/or modify it
14  * under the terms of the GNU General Public License as published by the Free
15  * Software Foundation; either version 2 of the License, or (at your option)
16  * any later version.
17  */
18 
19 #include <linux/device.h>
20 #include <linux/hid.h>
21 #include <linux/module.h>
22 
23 #include "hid-ids.h"
24 #include "hid-lg.h"
25 
26 #define LG_RDESC		0x001
27 #define LG_BAD_RELATIVE_KEYS	0x002
28 #define LG_DUPLICATE_USAGES	0x004
29 #define LG_EXPANDED_KEYMAP	0x010
30 #define LG_IGNORE_DOUBLED_WHEEL	0x020
31 #define LG_WIRELESS		0x040
32 #define LG_INVERT_HWHEEL	0x080
33 #define LG_NOGET		0x100
34 #define LG_FF			0x200
35 #define LG_FF2			0x400
36 
37 /*
38  * Certain Logitech keyboards send in report #3 keys which are far
39  * above the logical maximum described in descriptor. This extends
40  * the original value of 0x28c of logical maximum to 0x104d
41  */
42 static void lg_report_fixup(struct hid_device *hdev, __u8 *rdesc,
43 		unsigned int rsize)
44 {
45 	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
46 
47 	if ((quirks & LG_RDESC) && rsize >= 90 && rdesc[83] == 0x26 &&
48 			rdesc[84] == 0x8c && rdesc[85] == 0x02) {
49 		dev_info(&hdev->dev, "fixing up Logitech keyboard report "
50 				"descriptor\n");
51 		rdesc[84] = rdesc[89] = 0x4d;
52 		rdesc[85] = rdesc[90] = 0x10;
53 	}
54 }
55 
56 #define lg_map_key_clear(c)	hid_map_usage_clear(hi, usage, bit, max, \
57 		EV_KEY, (c))
58 
59 static int lg_ultrax_remote_mapping(struct hid_input *hi,
60 		struct hid_usage *usage, unsigned long **bit, int *max)
61 {
62 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
63 		return 0;
64 
65 	set_bit(EV_REP, hi->input->evbit);
66 	switch (usage->hid & HID_USAGE) {
67 	/* Reported on Logitech Ultra X Media Remote */
68 	case 0x004: lg_map_key_clear(KEY_AGAIN);	break;
69 	case 0x00d: lg_map_key_clear(KEY_HOME);		break;
70 	case 0x024: lg_map_key_clear(KEY_SHUFFLE);	break;
71 	case 0x025: lg_map_key_clear(KEY_TV);		break;
72 	case 0x026: lg_map_key_clear(KEY_MENU);		break;
73 	case 0x031: lg_map_key_clear(KEY_AUDIO);	break;
74 	case 0x032: lg_map_key_clear(KEY_TEXT);		break;
75 	case 0x033: lg_map_key_clear(KEY_LAST);		break;
76 	case 0x047: lg_map_key_clear(KEY_MP3);		break;
77 	case 0x048: lg_map_key_clear(KEY_DVD);		break;
78 	case 0x049: lg_map_key_clear(KEY_MEDIA);	break;
79 	case 0x04a: lg_map_key_clear(KEY_VIDEO);	break;
80 	case 0x04b: lg_map_key_clear(KEY_ANGLE);	break;
81 	case 0x04c: lg_map_key_clear(KEY_LANGUAGE);	break;
82 	case 0x04d: lg_map_key_clear(KEY_SUBTITLE);	break;
83 	case 0x051: lg_map_key_clear(KEY_RED);		break;
84 	case 0x052: lg_map_key_clear(KEY_CLOSE);	break;
85 
86 	default:
87 		return 0;
88 	}
89 	return 1;
90 }
91 
92 static int lg_dinovo_mapping(struct hid_input *hi, struct hid_usage *usage,
93 		unsigned long **bit, int *max)
94 {
95 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
96 		return 0;
97 
98 	switch (usage->hid & HID_USAGE) {
99 
100 	case 0x00d: lg_map_key_clear(KEY_MEDIA);	break;
101 	default:
102 		return 0;
103 
104 	}
105 	return 1;
106 }
107 
108 static int lg_wireless_mapping(struct hid_input *hi, struct hid_usage *usage,
109 		unsigned long **bit, int *max)
110 {
111 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
112 		return 0;
113 
114 	switch (usage->hid & HID_USAGE) {
115 	case 0x1001: lg_map_key_clear(KEY_MESSENGER);		break;
116 	case 0x1003: lg_map_key_clear(KEY_SOUND);		break;
117 	case 0x1004: lg_map_key_clear(KEY_VIDEO);		break;
118 	case 0x1005: lg_map_key_clear(KEY_AUDIO);		break;
119 	case 0x100a: lg_map_key_clear(KEY_DOCUMENTS);		break;
120 	case 0x1011: lg_map_key_clear(KEY_PREVIOUSSONG);	break;
121 	case 0x1012: lg_map_key_clear(KEY_NEXTSONG);		break;
122 	case 0x1013: lg_map_key_clear(KEY_CAMERA);		break;
123 	case 0x1014: lg_map_key_clear(KEY_MESSENGER);		break;
124 	case 0x1015: lg_map_key_clear(KEY_RECORD);		break;
125 	case 0x1016: lg_map_key_clear(KEY_PLAYER);		break;
126 	case 0x1017: lg_map_key_clear(KEY_EJECTCD);		break;
127 	case 0x1018: lg_map_key_clear(KEY_MEDIA);		break;
128 	case 0x1019: lg_map_key_clear(KEY_PROG1);		break;
129 	case 0x101a: lg_map_key_clear(KEY_PROG2);		break;
130 	case 0x101b: lg_map_key_clear(KEY_PROG3);		break;
131 	case 0x101f: lg_map_key_clear(KEY_ZOOMIN);		break;
132 	case 0x1020: lg_map_key_clear(KEY_ZOOMOUT);		break;
133 	case 0x1021: lg_map_key_clear(KEY_ZOOMRESET);		break;
134 	case 0x1023: lg_map_key_clear(KEY_CLOSE);		break;
135 	case 0x1027: lg_map_key_clear(KEY_MENU);		break;
136 	/* this one is marked as 'Rotate' */
137 	case 0x1028: lg_map_key_clear(KEY_ANGLE);		break;
138 	case 0x1029: lg_map_key_clear(KEY_SHUFFLE);		break;
139 	case 0x102a: lg_map_key_clear(KEY_BACK);		break;
140 	case 0x102b: lg_map_key_clear(KEY_CYCLEWINDOWS);	break;
141 	case 0x1041: lg_map_key_clear(KEY_BATTERY);		break;
142 	case 0x1042: lg_map_key_clear(KEY_WORDPROCESSOR);	break;
143 	case 0x1043: lg_map_key_clear(KEY_SPREADSHEET);		break;
144 	case 0x1044: lg_map_key_clear(KEY_PRESENTATION);	break;
145 	case 0x1045: lg_map_key_clear(KEY_UNDO);		break;
146 	case 0x1046: lg_map_key_clear(KEY_REDO);		break;
147 	case 0x1047: lg_map_key_clear(KEY_PRINT);		break;
148 	case 0x1048: lg_map_key_clear(KEY_SAVE);		break;
149 	case 0x1049: lg_map_key_clear(KEY_PROG1);		break;
150 	case 0x104a: lg_map_key_clear(KEY_PROG2);		break;
151 	case 0x104b: lg_map_key_clear(KEY_PROG3);		break;
152 	case 0x104c: lg_map_key_clear(KEY_PROG4);		break;
153 
154 	default:
155 		return 0;
156 	}
157 	return 1;
158 }
159 
160 static int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi,
161 		struct hid_field *field, struct hid_usage *usage,
162 		unsigned long **bit, int *max)
163 {
164 	/* extended mapping for certain Logitech hardware (Logitech cordless
165 	   desktop LX500) */
166 	static const u8 e_keymap[] = {
167 		  0,216,  0,213,175,156,  0,  0,  0,  0,
168 		144,  0,  0,  0,  0,  0,  0,  0,  0,212,
169 		174,167,152,161,112,  0,  0,  0,154,  0,
170 		  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
171 		  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
172 		  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
173 		  0,  0,  0,  0,  0,183,184,185,186,187,
174 		188,189,190,191,192,193,194,  0,  0,  0
175 	};
176 	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
177 	unsigned int hid = usage->hid;
178 
179 	if (hdev->product == USB_DEVICE_ID_LOGITECH_RECEIVER &&
180 			lg_ultrax_remote_mapping(hi, usage, bit, max))
181 		return 1;
182 
183 	if (hdev->product == USB_DEVICE_ID_DINOVO_MINI &&
184 			lg_dinovo_mapping(hi, usage, bit, max))
185 		return 1;
186 
187 	if ((quirks & LG_WIRELESS) && lg_wireless_mapping(hi, usage, bit, max))
188 		return 1;
189 
190 	if ((hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
191 		return 0;
192 
193 	hid &= HID_USAGE;
194 
195 	/* Special handling for Logitech Cordless Desktop */
196 	if (field->application == HID_GD_MOUSE) {
197 		if ((quirks & LG_IGNORE_DOUBLED_WHEEL) &&
198 				(hid == 7 || hid == 8))
199 			return -1;
200 	} else {
201 		if ((quirks & LG_EXPANDED_KEYMAP) &&
202 				hid < ARRAY_SIZE(e_keymap) &&
203 				e_keymap[hid] != 0) {
204 			hid_map_usage(hi, usage, bit, max, EV_KEY,
205 					e_keymap[hid]);
206 			return 1;
207 		}
208 	}
209 
210 	return 0;
211 }
212 
213 static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi,
214 		struct hid_field *field, struct hid_usage *usage,
215 		unsigned long **bit, int *max)
216 {
217 	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
218 
219 	if ((quirks & LG_BAD_RELATIVE_KEYS) && usage->type == EV_KEY &&
220 			(field->flags & HID_MAIN_ITEM_RELATIVE))
221 		field->flags &= ~HID_MAIN_ITEM_RELATIVE;
222 
223 	if ((quirks & LG_DUPLICATE_USAGES) && (usage->type == EV_KEY ||
224 			 usage->type == EV_REL || usage->type == EV_ABS))
225 		clear_bit(usage->code, *bit);
226 
227 	return 0;
228 }
229 
230 static int lg_event(struct hid_device *hdev, struct hid_field *field,
231 		struct hid_usage *usage, __s32 value)
232 {
233 	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
234 
235 	if ((quirks & LG_INVERT_HWHEEL) && usage->code == REL_HWHEEL) {
236 		input_event(field->hidinput->input, usage->type, usage->code,
237 				-value);
238 		return 1;
239 	}
240 
241 	return 0;
242 }
243 
244 static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
245 {
246 	unsigned long quirks = id->driver_data;
247 	unsigned int connect_mask = HID_CONNECT_DEFAULT;
248 	int ret;
249 
250 	hid_set_drvdata(hdev, (void *)quirks);
251 
252 	if (quirks & LG_NOGET)
253 		hdev->quirks |= HID_QUIRK_NOGET;
254 
255 	ret = hid_parse(hdev);
256 	if (ret) {
257 		dev_err(&hdev->dev, "parse failed\n");
258 		goto err_free;
259 	}
260 
261 	if (quirks & (LG_FF | LG_FF2))
262 		connect_mask &= ~HID_CONNECT_FF;
263 
264 	ret = hid_hw_start(hdev, connect_mask);
265 	if (ret) {
266 		dev_err(&hdev->dev, "hw start failed\n");
267 		goto err_free;
268 	}
269 
270 	if (quirks & LG_FF)
271 		lgff_init(hdev);
272 	if (quirks & LG_FF2)
273 		lg2ff_init(hdev);
274 
275 	return 0;
276 err_free:
277 	return ret;
278 }
279 
280 static const struct hid_device_id lg_devices[] = {
281 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER),
282 		.driver_data = LG_RDESC | LG_WIRELESS },
283 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER),
284 		.driver_data = LG_RDESC | LG_WIRELESS },
285 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2),
286 		.driver_data = LG_RDESC | LG_WIRELESS },
287 
288 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER),
289 		.driver_data = LG_BAD_RELATIVE_KEYS },
290 
291 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP),
292 		.driver_data = LG_DUPLICATE_USAGES },
293 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE),
294 		.driver_data = LG_DUPLICATE_USAGES },
295 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI),
296 		.driver_data = LG_DUPLICATE_USAGES },
297 
298 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD),
299 		.driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
300 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500),
301 		.driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
302 
303 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D),
304 		.driver_data = LG_NOGET },
305 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL),
306 		.driver_data = LG_NOGET | LG_FF },
307 
308 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD),
309 		.driver_data = LG_FF },
310 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2),
311 		.driver_data = LG_FF },
312 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D),
313 		.driver_data = LG_FF },
314 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO),
315 		.driver_data = LG_FF },
316 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL),
317 		.driver_data = LG_FF },
318 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2),
319 		.driver_data = LG_FF },
320 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL),
321 		.driver_data = LG_FF },
322 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ),
323 		.driver_data = LG_FF },
324 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2),
325 		.driver_data = LG_FF2 },
326 	{ }
327 };
328 MODULE_DEVICE_TABLE(hid, lg_devices);
329 
330 static struct hid_driver lg_driver = {
331 	.name = "logitech",
332 	.id_table = lg_devices,
333 	.report_fixup = lg_report_fixup,
334 	.input_mapping = lg_input_mapping,
335 	.input_mapped = lg_input_mapped,
336 	.event = lg_event,
337 	.probe = lg_probe,
338 };
339 
340 static int __init lg_init(void)
341 {
342 	return hid_register_driver(&lg_driver);
343 }
344 
345 static void __exit lg_exit(void)
346 {
347 	hid_unregister_driver(&lg_driver);
348 }
349 
350 module_init(lg_init);
351 module_exit(lg_exit);
352 MODULE_LICENSE("GPL");
353