xref: /linux/drivers/hid/hid-microsoft.c (revision f49f4ab95c301dbccad0efe85296d908b8ae7ad4)
1 /*
2  *  HID driver for some microsoft "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) 2008 Jiri Slaby
9  */
10 
11 /*
12  * This program is free software; you can redistribute it and/or modify it
13  * under the terms of the GNU General Public License as published by the Free
14  * Software Foundation; either version 2 of the License, or (at your option)
15  * any later version.
16  */
17 
18 #include <linux/device.h>
19 #include <linux/input.h>
20 #include <linux/hid.h>
21 #include <linux/module.h>
22 
23 #include "hid-ids.h"
24 
25 #define MS_HIDINPUT		0x01
26 #define MS_ERGONOMY		0x02
27 #define MS_PRESENTER		0x04
28 #define MS_RDESC		0x08
29 #define MS_NOGET		0x10
30 #define MS_DUPLICATE_USAGES	0x20
31 
32 /*
33  * Microsoft Wireless Desktop Receiver (Model 1028) has
34  * 'Usage Min/Max' where it ought to have 'Physical Min/Max'
35  */
36 static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc,
37 		unsigned int *rsize)
38 {
39 	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
40 
41 	if ((quirks & MS_RDESC) && *rsize == 571 && rdesc[557] == 0x19 &&
42 			rdesc[559] == 0x29) {
43 		hid_info(hdev, "fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n");
44 		rdesc[557] = 0x35;
45 		rdesc[559] = 0x45;
46 	}
47 	return rdesc;
48 }
49 
50 #define ms_map_key_clear(c)	hid_map_usage_clear(hi, usage, bit, max, \
51 					EV_KEY, (c))
52 static int ms_ergonomy_kb_quirk(struct hid_input *hi, struct hid_usage *usage,
53 		unsigned long **bit, int *max)
54 {
55 	struct input_dev *input = hi->input;
56 
57 	switch (usage->hid & HID_USAGE) {
58 	case 0xfd06: ms_map_key_clear(KEY_CHAT);	break;
59 	case 0xfd07: ms_map_key_clear(KEY_PHONE);	break;
60 	case 0xff05:
61 		set_bit(EV_REP, input->evbit);
62 		ms_map_key_clear(KEY_F13);
63 		set_bit(KEY_F14, input->keybit);
64 		set_bit(KEY_F15, input->keybit);
65 		set_bit(KEY_F16, input->keybit);
66 		set_bit(KEY_F17, input->keybit);
67 		set_bit(KEY_F18, input->keybit);
68 	default:
69 		return 0;
70 	}
71 	return 1;
72 }
73 
74 static int ms_presenter_8k_quirk(struct hid_input *hi, struct hid_usage *usage,
75 		unsigned long **bit, int *max)
76 {
77 	set_bit(EV_REP, hi->input->evbit);
78 	switch (usage->hid & HID_USAGE) {
79 	case 0xfd08: ms_map_key_clear(KEY_FORWARD);	break;
80 	case 0xfd09: ms_map_key_clear(KEY_BACK);	break;
81 	case 0xfd0b: ms_map_key_clear(KEY_PLAYPAUSE);	break;
82 	case 0xfd0e: ms_map_key_clear(KEY_CLOSE);	break;
83 	case 0xfd0f: ms_map_key_clear(KEY_PLAY);	break;
84 	default:
85 		return 0;
86 	}
87 	return 1;
88 }
89 
90 static int ms_input_mapping(struct hid_device *hdev, struct hid_input *hi,
91 		struct hid_field *field, struct hid_usage *usage,
92 		unsigned long **bit, int *max)
93 {
94 	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
95 
96 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
97 		return 0;
98 
99 	if (quirks & MS_ERGONOMY) {
100 		int ret = ms_ergonomy_kb_quirk(hi, usage, bit, max);
101 		if (ret)
102 			return ret;
103 	}
104 
105 	if ((quirks & MS_PRESENTER) &&
106 			ms_presenter_8k_quirk(hi, usage, bit, max))
107 		return 1;
108 
109 	return 0;
110 }
111 
112 static int ms_input_mapped(struct hid_device *hdev, struct hid_input *hi,
113 		struct hid_field *field, struct hid_usage *usage,
114 		unsigned long **bit, int *max)
115 {
116 	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
117 
118 	if (quirks & MS_DUPLICATE_USAGES)
119 		clear_bit(usage->code, *bit);
120 
121 	return 0;
122 }
123 
124 static int ms_event(struct hid_device *hdev, struct hid_field *field,
125 		struct hid_usage *usage, __s32 value)
126 {
127 	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
128 
129 	if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
130 			!usage->type)
131 		return 0;
132 
133 	/* Handling MS keyboards special buttons */
134 	if (quirks & MS_ERGONOMY && usage->hid == (HID_UP_MSVENDOR | 0xff05)) {
135 		struct input_dev *input = field->hidinput->input;
136 		static unsigned int last_key = 0;
137 		unsigned int key = 0;
138 		switch (value) {
139 		case 0x01: key = KEY_F14; break;
140 		case 0x02: key = KEY_F15; break;
141 		case 0x04: key = KEY_F16; break;
142 		case 0x08: key = KEY_F17; break;
143 		case 0x10: key = KEY_F18; break;
144 		}
145 		if (key) {
146 			input_event(input, usage->type, key, 1);
147 			last_key = key;
148 		} else
149 			input_event(input, usage->type, last_key, 0);
150 
151 		return 1;
152 	}
153 
154 	return 0;
155 }
156 
157 static int ms_probe(struct hid_device *hdev, const struct hid_device_id *id)
158 {
159 	unsigned long quirks = id->driver_data;
160 	int ret;
161 
162 	hid_set_drvdata(hdev, (void *)quirks);
163 
164 	if (quirks & MS_NOGET)
165 		hdev->quirks |= HID_QUIRK_NOGET;
166 
167 	ret = hid_parse(hdev);
168 	if (ret) {
169 		hid_err(hdev, "parse failed\n");
170 		goto err_free;
171 	}
172 
173 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | ((quirks & MS_HIDINPUT) ?
174 				HID_CONNECT_HIDINPUT_FORCE : 0));
175 	if (ret) {
176 		hid_err(hdev, "hw start failed\n");
177 		goto err_free;
178 	}
179 
180 	return 0;
181 err_free:
182 	return ret;
183 }
184 
185 static const struct hid_device_id ms_devices[] = {
186 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV),
187 		.driver_data = MS_HIDINPUT },
188 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K),
189 		.driver_data = MS_ERGONOMY },
190 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K),
191 		.driver_data = MS_ERGONOMY | MS_RDESC },
192 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB),
193 		.driver_data = MS_PRESENTER },
194 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K),
195 		.driver_data = MS_ERGONOMY },
196 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0),
197 		.driver_data = MS_NOGET },
198 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500),
199 		.driver_data = MS_DUPLICATE_USAGES },
200 
201 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT),
202 		.driver_data = MS_PRESENTER },
203 	{ }
204 };
205 MODULE_DEVICE_TABLE(hid, ms_devices);
206 
207 static struct hid_driver ms_driver = {
208 	.name = "microsoft",
209 	.id_table = ms_devices,
210 	.report_fixup = ms_report_fixup,
211 	.input_mapping = ms_input_mapping,
212 	.input_mapped = ms_input_mapped,
213 	.event = ms_event,
214 	.probe = ms_probe,
215 };
216 
217 static int __init ms_init(void)
218 {
219 	return hid_register_driver(&ms_driver);
220 }
221 
222 static void __exit ms_exit(void)
223 {
224 	hid_unregister_driver(&ms_driver);
225 }
226 
227 module_init(ms_init);
228 module_exit(ms_exit);
229 MODULE_LICENSE("GPL");
230