hid-lg.c revision fdc6807fcd09416c5537f479e1dcd624118e234c
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 *  Copyright (c) 2010 Hendrik Iben
11 */
12
13/*
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the Free
16 * Software Foundation; either version 2 of the License, or (at your option)
17 * any later version.
18 */
19
20#include <linux/device.h>
21#include <linux/hid.h>
22#include <linux/module.h>
23#include <linux/random.h>
24#include <linux/sched.h>
25#include <linux/wait.h>
26
27#include "hid-ids.h"
28#include "hid-lg.h"
29
30#define LG_RDESC		0x001
31#define LG_BAD_RELATIVE_KEYS	0x002
32#define LG_DUPLICATE_USAGES	0x004
33#define LG_EXPANDED_KEYMAP	0x010
34#define LG_IGNORE_DOUBLED_WHEEL	0x020
35#define LG_WIRELESS		0x040
36#define LG_INVERT_HWHEEL	0x080
37#define LG_NOGET		0x100
38#define LG_FF			0x200
39#define LG_FF2			0x400
40#define LG_RDESC_REL_ABS	0x800
41#define LG_FF3			0x1000
42#define LG_FF4			0x2000
43
44/*
45 * Certain Logitech keyboards send in report #3 keys which are far
46 * above the logical maximum described in descriptor. This extends
47 * the original value of 0x28c of logical maximum to 0x104d
48 */
49static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc,
50		unsigned int *rsize)
51{
52	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
53
54	if ((quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 &&
55			rdesc[84] == 0x8c && rdesc[85] == 0x02) {
56		hid_info(hdev,
57			 "fixing up Logitech keyboard report descriptor\n");
58		rdesc[84] = rdesc[89] = 0x4d;
59		rdesc[85] = rdesc[90] = 0x10;
60	}
61	if ((quirks & LG_RDESC_REL_ABS) && *rsize >= 50 &&
62			rdesc[32] == 0x81 && rdesc[33] == 0x06 &&
63			rdesc[49] == 0x81 && rdesc[50] == 0x06) {
64		hid_info(hdev,
65			 "fixing up rel/abs in Logitech report descriptor\n");
66		rdesc[33] = rdesc[50] = 0x02;
67	}
68	if ((quirks & LG_FF4) && *rsize >= 101 &&
69			rdesc[41] == 0x95 && rdesc[42] == 0x0B &&
70			rdesc[47] == 0x05 && rdesc[48] == 0x09) {
71		hid_info(hdev, "fixing up Logitech Speed Force Wireless button descriptor\n");
72		rdesc[41] = 0x05;
73		rdesc[42] = 0x09;
74		rdesc[47] = 0x95;
75		rdesc[48] = 0x0B;
76	}
77	return rdesc;
78}
79
80#define lg_map_key_clear(c)	hid_map_usage_clear(hi, usage, bit, max, \
81		EV_KEY, (c))
82
83static int lg_ultrax_remote_mapping(struct hid_input *hi,
84		struct hid_usage *usage, unsigned long **bit, int *max)
85{
86	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
87		return 0;
88
89	set_bit(EV_REP, hi->input->evbit);
90	switch (usage->hid & HID_USAGE) {
91	/* Reported on Logitech Ultra X Media Remote */
92	case 0x004: lg_map_key_clear(KEY_AGAIN);	break;
93	case 0x00d: lg_map_key_clear(KEY_HOME);		break;
94	case 0x024: lg_map_key_clear(KEY_SHUFFLE);	break;
95	case 0x025: lg_map_key_clear(KEY_TV);		break;
96	case 0x026: lg_map_key_clear(KEY_MENU);		break;
97	case 0x031: lg_map_key_clear(KEY_AUDIO);	break;
98	case 0x032: lg_map_key_clear(KEY_TEXT);		break;
99	case 0x033: lg_map_key_clear(KEY_LAST);		break;
100	case 0x047: lg_map_key_clear(KEY_MP3);		break;
101	case 0x048: lg_map_key_clear(KEY_DVD);		break;
102	case 0x049: lg_map_key_clear(KEY_MEDIA);	break;
103	case 0x04a: lg_map_key_clear(KEY_VIDEO);	break;
104	case 0x04b: lg_map_key_clear(KEY_ANGLE);	break;
105	case 0x04c: lg_map_key_clear(KEY_LANGUAGE);	break;
106	case 0x04d: lg_map_key_clear(KEY_SUBTITLE);	break;
107	case 0x051: lg_map_key_clear(KEY_RED);		break;
108	case 0x052: lg_map_key_clear(KEY_CLOSE);	break;
109
110	default:
111		return 0;
112	}
113	return 1;
114}
115
116static int lg_dinovo_mapping(struct hid_input *hi, struct hid_usage *usage,
117		unsigned long **bit, int *max)
118{
119	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
120		return 0;
121
122	switch (usage->hid & HID_USAGE) {
123
124	case 0x00d: lg_map_key_clear(KEY_MEDIA);	break;
125	default:
126		return 0;
127
128	}
129	return 1;
130}
131
132static int lg_wireless_mapping(struct hid_input *hi, struct hid_usage *usage,
133		unsigned long **bit, int *max)
134{
135	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
136		return 0;
137
138	switch (usage->hid & HID_USAGE) {
139	case 0x1001: lg_map_key_clear(KEY_MESSENGER);		break;
140	case 0x1003: lg_map_key_clear(KEY_SOUND);		break;
141	case 0x1004: lg_map_key_clear(KEY_VIDEO);		break;
142	case 0x1005: lg_map_key_clear(KEY_AUDIO);		break;
143	case 0x100a: lg_map_key_clear(KEY_DOCUMENTS);		break;
144	/* The following two entries are Playlist 1 and 2 on the MX3200 */
145	case 0x100f: lg_map_key_clear(KEY_FN_1);		break;
146	case 0x1010: lg_map_key_clear(KEY_FN_2);		break;
147	case 0x1011: lg_map_key_clear(KEY_PREVIOUSSONG);	break;
148	case 0x1012: lg_map_key_clear(KEY_NEXTSONG);		break;
149	case 0x1013: lg_map_key_clear(KEY_CAMERA);		break;
150	case 0x1014: lg_map_key_clear(KEY_MESSENGER);		break;
151	case 0x1015: lg_map_key_clear(KEY_RECORD);		break;
152	case 0x1016: lg_map_key_clear(KEY_PLAYER);		break;
153	case 0x1017: lg_map_key_clear(KEY_EJECTCD);		break;
154	case 0x1018: lg_map_key_clear(KEY_MEDIA);		break;
155	case 0x1019: lg_map_key_clear(KEY_PROG1);		break;
156	case 0x101a: lg_map_key_clear(KEY_PROG2);		break;
157	case 0x101b: lg_map_key_clear(KEY_PROG3);		break;
158	case 0x101c: lg_map_key_clear(KEY_CYCLEWINDOWS);	break;
159	case 0x101f: lg_map_key_clear(KEY_ZOOMIN);		break;
160	case 0x1020: lg_map_key_clear(KEY_ZOOMOUT);		break;
161	case 0x1021: lg_map_key_clear(KEY_ZOOMRESET);		break;
162	case 0x1023: lg_map_key_clear(KEY_CLOSE);		break;
163	case 0x1027: lg_map_key_clear(KEY_MENU);		break;
164	/* this one is marked as 'Rotate' */
165	case 0x1028: lg_map_key_clear(KEY_ANGLE);		break;
166	case 0x1029: lg_map_key_clear(KEY_SHUFFLE);		break;
167	case 0x102a: lg_map_key_clear(KEY_BACK);		break;
168	case 0x102b: lg_map_key_clear(KEY_CYCLEWINDOWS);	break;
169	case 0x102d: lg_map_key_clear(KEY_WWW);			break;
170	/* The following two are 'Start/answer call' and 'End/reject call'
171	   on the MX3200 */
172	case 0x1031: lg_map_key_clear(KEY_OK);			break;
173	case 0x1032: lg_map_key_clear(KEY_CANCEL);		break;
174	case 0x1041: lg_map_key_clear(KEY_BATTERY);		break;
175	case 0x1042: lg_map_key_clear(KEY_WORDPROCESSOR);	break;
176	case 0x1043: lg_map_key_clear(KEY_SPREADSHEET);		break;
177	case 0x1044: lg_map_key_clear(KEY_PRESENTATION);	break;
178	case 0x1045: lg_map_key_clear(KEY_UNDO);		break;
179	case 0x1046: lg_map_key_clear(KEY_REDO);		break;
180	case 0x1047: lg_map_key_clear(KEY_PRINT);		break;
181	case 0x1048: lg_map_key_clear(KEY_SAVE);		break;
182	case 0x1049: lg_map_key_clear(KEY_PROG1);		break;
183	case 0x104a: lg_map_key_clear(KEY_PROG2);		break;
184	case 0x104b: lg_map_key_clear(KEY_PROG3);		break;
185	case 0x104c: lg_map_key_clear(KEY_PROG4);		break;
186
187	default:
188		return 0;
189	}
190	return 1;
191}
192
193static int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi,
194		struct hid_field *field, struct hid_usage *usage,
195		unsigned long **bit, int *max)
196{
197	/* extended mapping for certain Logitech hardware (Logitech cordless
198	   desktop LX500) */
199	static const u8 e_keymap[] = {
200		  0,216,  0,213,175,156,  0,  0,  0,  0,
201		144,  0,  0,  0,  0,  0,  0,  0,  0,212,
202		174,167,152,161,112,  0,  0,  0,154,  0,
203		  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
204		  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
205		  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
206		  0,  0,  0,  0,  0,183,184,185,186,187,
207		188,189,190,191,192,193,194,  0,  0,  0
208	};
209	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
210	unsigned int hid = usage->hid;
211
212	if (hdev->product == USB_DEVICE_ID_LOGITECH_RECEIVER &&
213			lg_ultrax_remote_mapping(hi, usage, bit, max))
214		return 1;
215
216	if (hdev->product == USB_DEVICE_ID_DINOVO_MINI &&
217			lg_dinovo_mapping(hi, usage, bit, max))
218		return 1;
219
220	if ((quirks & LG_WIRELESS) && lg_wireless_mapping(hi, usage, bit, max))
221		return 1;
222
223	if ((hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
224		return 0;
225
226	hid &= HID_USAGE;
227
228	/* Special handling for Logitech Cordless Desktop */
229	if (field->application == HID_GD_MOUSE) {
230		if ((quirks & LG_IGNORE_DOUBLED_WHEEL) &&
231				(hid == 7 || hid == 8))
232			return -1;
233	} else {
234		if ((quirks & LG_EXPANDED_KEYMAP) &&
235				hid < ARRAY_SIZE(e_keymap) &&
236				e_keymap[hid] != 0) {
237			hid_map_usage(hi, usage, bit, max, EV_KEY,
238					e_keymap[hid]);
239			return 1;
240		}
241	}
242
243	return 0;
244}
245
246static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi,
247		struct hid_field *field, struct hid_usage *usage,
248		unsigned long **bit, int *max)
249{
250	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
251
252	if ((quirks & LG_BAD_RELATIVE_KEYS) && usage->type == EV_KEY &&
253			(field->flags & HID_MAIN_ITEM_RELATIVE))
254		field->flags &= ~HID_MAIN_ITEM_RELATIVE;
255
256	if ((quirks & LG_DUPLICATE_USAGES) && (usage->type == EV_KEY ||
257			 usage->type == EV_REL || usage->type == EV_ABS))
258		clear_bit(usage->code, *bit);
259
260	return 0;
261}
262
263static int lg_event(struct hid_device *hdev, struct hid_field *field,
264		struct hid_usage *usage, __s32 value)
265{
266	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
267
268	if ((quirks & LG_INVERT_HWHEEL) && usage->code == REL_HWHEEL) {
269		input_event(field->hidinput->input, usage->type, usage->code,
270				-value);
271		return 1;
272	}
273
274	return 0;
275}
276
277static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
278{
279	unsigned long quirks = id->driver_data;
280	unsigned int connect_mask = HID_CONNECT_DEFAULT;
281	int ret;
282
283	hid_set_drvdata(hdev, (void *)quirks);
284
285	if (quirks & LG_NOGET)
286		hdev->quirks |= HID_QUIRK_NOGET;
287
288	ret = hid_parse(hdev);
289	if (ret) {
290		hid_err(hdev, "parse failed\n");
291		goto err_free;
292	}
293
294	if (quirks & (LG_FF | LG_FF2 | LG_FF3))
295		connect_mask &= ~HID_CONNECT_FF;
296
297	ret = hid_hw_start(hdev, connect_mask);
298	if (ret) {
299		hid_err(hdev, "hw start failed\n");
300		goto err_free;
301	}
302
303	if (quirks & LG_FF4) {
304		unsigned char buf[] = { 0x00, 0xAF,  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
305
306		ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
307
308		if (ret >= 0) {
309			/* insert a little delay of 10 jiffies ~ 40ms */
310			wait_queue_head_t wait;
311			init_waitqueue_head (&wait);
312			wait_event_interruptible_timeout(wait, 0, 10);
313
314			/* Select random Address */
315			buf[1] = 0xB2;
316			get_random_bytes(&buf[2], 2);
317
318			ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
319		}
320	}
321
322	if (quirks & LG_FF)
323		lgff_init(hdev);
324	if (quirks & LG_FF2)
325		lg2ff_init(hdev);
326	if (quirks & LG_FF3)
327		lg3ff_init(hdev);
328	if (quirks & LG_FF4)
329		lg4ff_init(hdev);
330
331	return 0;
332err_free:
333	return ret;
334}
335
336static const struct hid_device_id lg_devices[] = {
337	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER),
338		.driver_data = LG_RDESC | LG_WIRELESS },
339	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER),
340		.driver_data = LG_RDESC | LG_WIRELESS },
341	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2),
342		.driver_data = LG_RDESC | LG_WIRELESS },
343
344	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER),
345		.driver_data = LG_BAD_RELATIVE_KEYS },
346
347	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP),
348		.driver_data = LG_DUPLICATE_USAGES },
349	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE),
350		.driver_data = LG_DUPLICATE_USAGES },
351	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI),
352		.driver_data = LG_DUPLICATE_USAGES },
353
354	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD),
355		.driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
356	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500),
357		.driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
358
359	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D),
360		.driver_data = LG_NOGET },
361	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL),
362		.driver_data = LG_NOGET | LG_FF },
363
364	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD),
365		.driver_data = LG_FF2 },
366	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD),
367		.driver_data = LG_FF },
368	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2),
369		.driver_data = LG_FF },
370	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D),
371		.driver_data = LG_FF },
372	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO),
373		.driver_data = LG_FF },
374	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL),
375		.driver_data = LG_FF },
376	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2),
377		.driver_data = LG_FF },
378	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL),
379		.driver_data = LG_FF },
380	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL),
381		.driver_data = LG_FF },
382	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL),
383		.driver_data = LG_FF },
384	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL),
385		.driver_data = LG_FF4 },
386	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ),
387		.driver_data = LG_FF },
388	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2),
389		.driver_data = LG_FF2 },
390	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940),
391		.driver_data = LG_FF3 },
392	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR),
393		.driver_data = LG_RDESC_REL_ABS },
394	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER),
395		.driver_data = LG_RDESC_REL_ABS },
396	{ }
397};
398
399MODULE_DEVICE_TABLE(hid, lg_devices);
400
401static struct hid_driver lg_driver = {
402	.name = "logitech",
403	.id_table = lg_devices,
404	.report_fixup = lg_report_fixup,
405	.input_mapping = lg_input_mapping,
406	.input_mapped = lg_input_mapped,
407	.event = lg_event,
408	.probe = lg_probe,
409};
410
411static int __init lg_init(void)
412{
413	return hid_register_driver(&lg_driver);
414}
415
416static void __exit lg_exit(void)
417{
418	hid_unregister_driver(&lg_driver);
419}
420
421module_init(lg_init);
422module_exit(lg_exit);
423MODULE_LICENSE("GPL");
424