Blame view

drivers/hid/hid-input.c 36.4 KB
dde5845a5   Jiri Kosina   [PATCH] Generic H...
1
  /*
dde5845a5   Jiri Kosina   [PATCH] Generic H...
2
   *  Copyright (c) 2000-2001 Vojtech Pavlik
7d39e8499   Jiri Kosina   HID: update copyr...
3
   *  Copyright (c) 2006-2010 Jiri Kosina
dde5845a5   Jiri Kosina   [PATCH] Generic H...
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   *
   *  HID to Linux Input mapping
   */
  
  /*
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
   *
   * Should you need to contact me, the author, you can do so either by
   * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
   * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
   */
  
  #include <linux/module.h>
  #include <linux/slab.h>
  #include <linux/kernel.h>
dde5845a5   Jiri Kosina   [PATCH] Generic H...
31

dde5845a5   Jiri Kosina   [PATCH] Generic H...
32
  #include <linux/hid.h>
c080d89ad   Jiri Kosina   HID: hid debug fr...
33
  #include <linux/hid-debug.h>
dde5845a5   Jiri Kosina   [PATCH] Generic H...
34

bbc21cfd5   Jeremy Fitzhardinge   hid-input/battery...
35
  #include "hid-ids.h"
dde5845a5   Jiri Kosina   [PATCH] Generic H...
36
37
38
39
40
41
42
43
44
45
46
47
  #define unk	KEY_UNKNOWN
  
  static const unsigned char hid_keyboard[256] = {
  	  0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
  	 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,
  	  4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26,
  	 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
  	 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
  	105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
  	 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
  	191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
  	115,114,unk,unk,unk,121,unk, 89, 93,124, 92, 94, 95,unk,unk,unk,
437f3b199   Jarod Wilson   HID: assorted usa...
48
  	122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk,
dde5845a5   Jiri Kosina   [PATCH] Generic H...
49
  	unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
1fe8736da   Jiri Kosina   HID: add support ...
50
  	unk,unk,unk,unk,unk,unk,179,180,unk,unk,unk,unk,unk,unk,unk,unk,
dde5845a5   Jiri Kosina   [PATCH] Generic H...
51
  	unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
437f3b199   Jarod Wilson   HID: assorted usa...
52
  	unk,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk,unk,unk,unk,unk,
dde5845a5   Jiri Kosina   [PATCH] Generic H...
53
54
55
56
57
58
59
60
  	 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
  	150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
  };
  
  static const struct {
  	__s32 x;
  	__s32 y;
  }  hid_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
022e8c4d0   Jiri Slaby   HID: move usage i...
61
62
63
64
  #define map_abs(c)	hid_map_usage(hidinput, usage, &bit, &max, EV_ABS, (c))
  #define map_rel(c)	hid_map_usage(hidinput, usage, &bit, &max, EV_REL, (c))
  #define map_key(c)	hid_map_usage(hidinput, usage, &bit, &max, EV_KEY, (c))
  #define map_led(c)	hid_map_usage(hidinput, usage, &bit, &max, EV_LED, (c))
dde5845a5   Jiri Kosina   [PATCH] Generic H...
65

022e8c4d0   Jiri Slaby   HID: move usage i...
66
67
68
69
  #define map_abs_clear(c)	hid_map_usage_clear(hidinput, usage, &bit, \
  		&max, EV_ABS, (c))
  #define map_key_clear(c)	hid_map_usage_clear(hidinput, usage, &bit, \
  		&max, EV_KEY, (c))
dde5845a5   Jiri Kosina   [PATCH] Generic H...
70

a0bf0ea80   Dmitry Torokhov   Input: hid-input ...
71
72
  static bool match_scancode(struct hid_usage *usage,
  			   unsigned int cur_idx, unsigned int scancode)
fe7ba31fe   Marvin Raaijmakers   HID: add hooks fo...
73
  {
a0bf0ea80   Dmitry Torokhov   Input: hid-input ...
74
  	return (usage->hid & (HID_USAGE_PAGE | HID_USAGE)) == scancode;
fe7ba31fe   Marvin Raaijmakers   HID: add hooks fo...
75
  }
a0bf0ea80   Dmitry Torokhov   Input: hid-input ...
76
77
  static bool match_keycode(struct hid_usage *usage,
  			  unsigned int cur_idx, unsigned int keycode)
fe7ba31fe   Marvin Raaijmakers   HID: add hooks fo...
78
  {
f5854fad3   Dmitry Torokhov   Input: hid-input ...
79
80
81
82
  	/*
  	 * We should exclude unmapped usages when doing lookup by keycode.
  	 */
  	return (usage->type == EV_KEY && usage->code == keycode);
a0bf0ea80   Dmitry Torokhov   Input: hid-input ...
83
  }
58b939959   Dmitry Torokhov   Input: scancode i...
84

a0bf0ea80   Dmitry Torokhov   Input: hid-input ...
85
86
87
88
  static bool match_index(struct hid_usage *usage,
  			unsigned int cur_idx, unsigned int idx)
  {
  	return cur_idx == idx;
fe7ba31fe   Marvin Raaijmakers   HID: add hooks fo...
89
  }
a0bf0ea80   Dmitry Torokhov   Input: hid-input ...
90
91
  typedef bool (*hid_usage_cmp_t)(struct hid_usage *usage,
  				unsigned int cur_idx, unsigned int val);
fe7ba31fe   Marvin Raaijmakers   HID: add hooks fo...
92
  static struct hid_usage *hidinput_find_key(struct hid_device *hid,
a0bf0ea80   Dmitry Torokhov   Input: hid-input ...
93
94
95
  					   hid_usage_cmp_t match,
  					   unsigned int value,
  					   unsigned int *usage_idx)
fe7ba31fe   Marvin Raaijmakers   HID: add hooks fo...
96
  {
a0bf0ea80   Dmitry Torokhov   Input: hid-input ...
97
  	unsigned int i, j, k, cur_idx = 0;
fe7ba31fe   Marvin Raaijmakers   HID: add hooks fo...
98
99
100
101
102
103
  	struct hid_report *report;
  	struct hid_usage *usage;
  
  	for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
  		list_for_each_entry(report, &hid->report_enum[k].report_list, list) {
  			for (i = 0; i < report->maxfield; i++) {
a0bf0ea80   Dmitry Torokhov   Input: hid-input ...
104
  				for (j = 0; j < report->field[i]->maxusage; j++) {
fe7ba31fe   Marvin Raaijmakers   HID: add hooks fo...
105
  					usage = report->field[i]->usage + j;
f5854fad3   Dmitry Torokhov   Input: hid-input ...
106
  					if (usage->type == EV_KEY || usage->type == 0) {
a0bf0ea80   Dmitry Torokhov   Input: hid-input ...
107
108
109
110
111
112
113
  						if (match(usage, cur_idx, value)) {
  							if (usage_idx)
  								*usage_idx = cur_idx;
  							return usage;
  						}
  						cur_idx++;
  					}
fe7ba31fe   Marvin Raaijmakers   HID: add hooks fo...
114
115
116
117
118
119
  				}
  			}
  		}
  	}
  	return NULL;
  }
a0bf0ea80   Dmitry Torokhov   Input: hid-input ...
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
  static struct hid_usage *hidinput_locate_usage(struct hid_device *hid,
  					const struct input_keymap_entry *ke,
  					unsigned int *index)
  {
  	struct hid_usage *usage;
  	unsigned int scancode;
  
  	if (ke->flags & INPUT_KEYMAP_BY_INDEX)
  		usage = hidinput_find_key(hid, match_index, ke->index, index);
  	else if (input_scancode_to_scalar(ke, &scancode) == 0)
  		usage = hidinput_find_key(hid, match_scancode, scancode, index);
  	else
  		usage = NULL;
  
  	return usage;
  }
58b939959   Dmitry Torokhov   Input: scancode i...
136
  static int hidinput_getkeycode(struct input_dev *dev,
a0bf0ea80   Dmitry Torokhov   Input: hid-input ...
137
  			       struct input_keymap_entry *ke)
fe7ba31fe   Marvin Raaijmakers   HID: add hooks fo...
138
  {
f202df600   Dmitry Torokhov   HID: Don't access...
139
  	struct hid_device *hid = input_get_drvdata(dev);
fe7ba31fe   Marvin Raaijmakers   HID: add hooks fo...
140
  	struct hid_usage *usage;
a0bf0ea80   Dmitry Torokhov   Input: hid-input ...
141
  	unsigned int scancode, index;
77b296629   Jiri Kosina   HID: fix whitespa...
142

a0bf0ea80   Dmitry Torokhov   Input: hid-input ...
143
  	usage = hidinput_locate_usage(hid, ke, &index);
fe7ba31fe   Marvin Raaijmakers   HID: add hooks fo...
144
  	if (usage) {
f5854fad3   Dmitry Torokhov   Input: hid-input ...
145
146
  		ke->keycode = usage->type == EV_KEY ?
  				usage->code : KEY_RESERVED;
a0bf0ea80   Dmitry Torokhov   Input: hid-input ...
147
148
149
150
  		ke->index = index;
  		scancode = usage->hid & (HID_USAGE_PAGE | HID_USAGE);
  		ke->len = sizeof(scancode);
  		memcpy(ke->scancode, &scancode, sizeof(scancode));
fe7ba31fe   Marvin Raaijmakers   HID: add hooks fo...
151
152
  		return 0;
  	}
a0bf0ea80   Dmitry Torokhov   Input: hid-input ...
153

fe7ba31fe   Marvin Raaijmakers   HID: add hooks fo...
154
155
  	return -EINVAL;
  }
58b939959   Dmitry Torokhov   Input: scancode i...
156
  static int hidinput_setkeycode(struct input_dev *dev,
a0bf0ea80   Dmitry Torokhov   Input: hid-input ...
157
158
  			       const struct input_keymap_entry *ke,
  			       unsigned int *old_keycode)
fe7ba31fe   Marvin Raaijmakers   HID: add hooks fo...
159
  {
f202df600   Dmitry Torokhov   HID: Don't access...
160
  	struct hid_device *hid = input_get_drvdata(dev);
fe7ba31fe   Marvin Raaijmakers   HID: add hooks fo...
161
  	struct hid_usage *usage;
77b296629   Jiri Kosina   HID: fix whitespa...
162

a0bf0ea80   Dmitry Torokhov   Input: hid-input ...
163
  	usage = hidinput_locate_usage(hid, ke, NULL);
fe7ba31fe   Marvin Raaijmakers   HID: add hooks fo...
164
  	if (usage) {
f5854fad3   Dmitry Torokhov   Input: hid-input ...
165
166
  		*old_keycode = usage->type == EV_KEY ?
  				usage->code : KEY_RESERVED;
a0bf0ea80   Dmitry Torokhov   Input: hid-input ...
167
  		usage->code = ke->keycode;
77b296629   Jiri Kosina   HID: fix whitespa...
168

a0bf0ea80   Dmitry Torokhov   Input: hid-input ...
169
  		clear_bit(*old_keycode, dev->keybit);
fe7ba31fe   Marvin Raaijmakers   HID: add hooks fo...
170
  		set_bit(usage->code, dev->keybit);
587d14520   Joe Perches   HID: Remove KERN_...
171
172
  		dbg_hid("Assigned keycode %d to HID usage code %x
  ",
a0bf0ea80   Dmitry Torokhov   Input: hid-input ...
173
174
175
176
177
178
179
180
  			usage->code, usage->hid);
  
  		/*
  		 * Set the keybit for the old keycode if the old keycode is used
  		 * by another key
  		 */
  		if (hidinput_find_key(hid, match_keycode, *old_keycode, NULL))
  			set_bit(*old_keycode, dev->keybit);
77b296629   Jiri Kosina   HID: fix whitespa...
181

fe7ba31fe   Marvin Raaijmakers   HID: add hooks fo...
182
183
  		return 0;
  	}
77b296629   Jiri Kosina   HID: fix whitespa...
184

fe7ba31fe   Marvin Raaijmakers   HID: add hooks fo...
185
186
  	return -EINVAL;
  }
4ea6e4ffb   Nikolai Kondrashov   HID: add absolute...
187
188
189
190
191
192
193
194
195
196
197
198
  /**
   * hidinput_calc_abs_res - calculate an absolute axis resolution
   * @field: the HID report field to calculate resolution for
   * @code: axis code
   *
   * The formula is:
   *                         (logical_maximum - logical_minimum)
   * resolution = ----------------------------------------------------------
   *              (physical_maximum - physical_minimum) * 10 ^ unit_exponent
   *
   * as seen in the HID specification v1.11 6.2.2.7 Global Items.
   *
83ed79c56   Dmitry Torokhov   HID: length resol...
199
200
   * Only exponent 1 length units are processed. Centimeters and inches are
   * converted to millimeters. Degrees are converted to radians.
4ea6e4ffb   Nikolai Kondrashov   HID: add absolute...
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
   */
  static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
  {
  	__s32 unit_exponent = field->unit_exponent;
  	__s32 logical_extents = field->logical_maximum -
  					field->logical_minimum;
  	__s32 physical_extents = field->physical_maximum -
  					field->physical_minimum;
  	__s32 prev;
  
  	/* Check if the extents are sane */
  	if (logical_extents <= 0 || physical_extents <= 0)
  		return 0;
  
  	/*
  	 * Verify and convert units.
  	 * See HID specification v1.11 6.2.2.7 Global Items for unit decoding
  	 */
  	if (code == ABS_X || code == ABS_Y || code == ABS_Z) {
  		if (field->unit == 0x11) {		/* If centimeters */
83ed79c56   Dmitry Torokhov   HID: length resol...
221
222
223
224
225
226
227
  			/* Convert to millimeters */
  			unit_exponent += 1;
  		} else if (field->unit == 0x13) {	/* If inches */
  			/* Convert to millimeters */
  			prev = physical_extents;
  			physical_extents *= 254;
  			if (physical_extents < prev)
4ea6e4ffb   Nikolai Kondrashov   HID: add absolute...
228
  				return 0;
83ed79c56   Dmitry Torokhov   HID: length resol...
229
230
  			unit_exponent -= 1;
  		} else {
4ea6e4ffb   Nikolai Kondrashov   HID: add absolute...
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
  			return 0;
  		}
  	} else if (code == ABS_RX || code == ABS_RY || code == ABS_RZ) {
  		if (field->unit == 0x14) {		/* If degrees */
  			/* Convert to radians */
  			prev = logical_extents;
  			logical_extents *= 573;
  			if (logical_extents < prev)
  				return 0;
  			unit_exponent += 1;
  		} else if (field->unit != 0x12) {	/* If not radians */
  			return 0;
  		}
  	} else {
  		return 0;
  	}
  
  	/* Apply negative unit exponent */
  	for (; unit_exponent < 0; unit_exponent++) {
  		prev = logical_extents;
  		logical_extents *= 10;
  		if (logical_extents < prev)
  			return 0;
  	}
  	/* Apply positive unit exponent */
  	for (; unit_exponent > 0; unit_exponent--) {
  		prev = physical_extents;
  		physical_extents *= 10;
  		if (physical_extents < prev)
  			return 0;
  	}
  
  	/* Calculate resolution */
  	return logical_extents / physical_extents;
  }
4f5ca836b   Jeremy Fitzhardinge   HID: hid-input: a...
266
267
268
269
270
271
  #ifdef CONFIG_HID_BATTERY_STRENGTH
  static enum power_supply_property hidinput_battery_props[] = {
  	POWER_SUPPLY_PROP_PRESENT,
  	POWER_SUPPLY_PROP_ONLINE,
  	POWER_SUPPLY_PROP_CAPACITY,
  	POWER_SUPPLY_PROP_MODEL_NAME,
c5a92aa3e   Daniel Nicoletti   hid-input: add su...
272
  	POWER_SUPPLY_PROP_STATUS
4f5ca836b   Jeremy Fitzhardinge   HID: hid-input: a...
273
  };
bbc21cfd5   Jeremy Fitzhardinge   hid-input/battery...
274
  #define HID_BATTERY_QUIRK_PERCENT	(1 << 0) /* always reports percent */
652aa6a9a   Jeremy Fitzhardinge   hid-input/battery...
275
  #define HID_BATTERY_QUIRK_FEATURE	(1 << 1) /* ask for feature report */
bbc21cfd5   Jeremy Fitzhardinge   hid-input/battery...
276
277
  
  static const struct hid_device_id hid_battery_quirks[] = {
652aa6a9a   Jeremy Fitzhardinge   hid-input/battery...
278
279
280
  	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
  			       USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI),
  	  HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
bbc21cfd5   Jeremy Fitzhardinge   hid-input/battery...
281
282
283
284
285
286
287
288
289
290
291
292
293
294
  	{}
  };
  
  static unsigned find_battery_quirk(struct hid_device *hdev)
  {
  	unsigned quirks = 0;
  	const struct hid_device_id *match;
  
  	match = hid_match_id(hdev, hid_battery_quirks);
  	if (match != NULL)
  		quirks = match->driver_data;
  
  	return quirks;
  }
4f5ca836b   Jeremy Fitzhardinge   HID: hid-input: a...
295
296
297
298
299
300
  static int hidinput_get_battery_property(struct power_supply *psy,
  					 enum power_supply_property prop,
  					 union power_supply_propval *val)
  {
  	struct hid_device *dev = container_of(psy, struct hid_device, battery);
  	int ret = 0;
ef5251993   Jeremy Fitzhardinge   hid-input/battery...
301
  	__u8 buf[2] = {};
4f5ca836b   Jeremy Fitzhardinge   HID: hid-input: a...
302
303
304
305
306
307
308
309
  
  	switch (prop) {
  	case POWER_SUPPLY_PROP_PRESENT:
  	case POWER_SUPPLY_PROP_ONLINE:
  		val->intval = 1;
  		break;
  
  	case POWER_SUPPLY_PROP_CAPACITY:
652aa6a9a   Jeremy Fitzhardinge   hid-input/battery...
310
311
312
313
314
315
316
  		ret = dev->hid_get_raw_report(dev, dev->battery_report_id,
  					      buf, sizeof(buf),
  					      dev->battery_report_type);
  
  		if (ret != 2) {
  			if (ret >= 0)
  				ret = -EINVAL;
c5a92aa3e   Daniel Nicoletti   hid-input: add su...
317
318
  			break;
  		}
4f5ca836b   Jeremy Fitzhardinge   HID: hid-input: a...
319
  		if (dev->battery_min < dev->battery_max &&
bbc21cfd5   Jeremy Fitzhardinge   hid-input/battery...
320
321
322
  		    buf[1] >= dev->battery_min &&
  		    buf[1] <= dev->battery_max)
  			val->intval = (100 * (buf[1] - dev->battery_min)) /
4f5ca836b   Jeremy Fitzhardinge   HID: hid-input: a...
323
  				(dev->battery_max - dev->battery_min);
4f5ca836b   Jeremy Fitzhardinge   HID: hid-input: a...
324
325
326
327
328
  		break;
  
  	case POWER_SUPPLY_PROP_MODEL_NAME:
  		val->strval = dev->name;
  		break;
c5a92aa3e   Daniel Nicoletti   hid-input: add su...
329
330
331
  	case POWER_SUPPLY_PROP_STATUS:
  		val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
  		break;
4f5ca836b   Jeremy Fitzhardinge   HID: hid-input: a...
332
333
334
335
336
337
338
  	default:
  		ret = -EINVAL;
  		break;
  	}
  
  	return ret;
  }
2f2e3f6d7   Jeremy Fitzhardinge   hid-input/battery...
339
  static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type, struct hid_field *field)
4f5ca836b   Jeremy Fitzhardinge   HID: hid-input: a...
340
341
342
  {
  	struct power_supply *battery = &dev->battery;
  	int ret;
bbc21cfd5   Jeremy Fitzhardinge   hid-input/battery...
343
  	unsigned quirks;
2f2e3f6d7   Jeremy Fitzhardinge   hid-input/battery...
344
345
346
347
  	s32 min, max;
  
  	if (field->usage->hid != HID_DC_BATTERYSTRENGTH)
  		return false;	/* no match */
4f5ca836b   Jeremy Fitzhardinge   HID: hid-input: a...
348
349
  
  	if (battery->name != NULL)
2f2e3f6d7   Jeremy Fitzhardinge   hid-input/battery...
350
  		goto out;	/* already initialized? */
4f5ca836b   Jeremy Fitzhardinge   HID: hid-input: a...
351
352
353
  
  	battery->name = kasprintf(GFP_KERNEL, "hid-%s-battery", dev->uniq);
  	if (battery->name == NULL)
2f2e3f6d7   Jeremy Fitzhardinge   hid-input/battery...
354
  		goto out;
4f5ca836b   Jeremy Fitzhardinge   HID: hid-input: a...
355
356
357
358
359
360
  
  	battery->type = POWER_SUPPLY_TYPE_BATTERY;
  	battery->properties = hidinput_battery_props;
  	battery->num_properties = ARRAY_SIZE(hidinput_battery_props);
  	battery->use_for_apm = 0;
  	battery->get_property = hidinput_get_battery_property;
bbc21cfd5   Jeremy Fitzhardinge   hid-input/battery...
361
  	quirks = find_battery_quirk(dev);
652aa6a9a   Jeremy Fitzhardinge   hid-input/battery...
362
363
364
  	hid_dbg(dev, "device %x:%x:%x %d quirks %d
  ",
  		dev->bus, dev->vendor, dev->product, dev->version, quirks);
2f2e3f6d7   Jeremy Fitzhardinge   hid-input/battery...
365
366
  	min = field->logical_minimum;
  	max = field->logical_maximum;
bbc21cfd5   Jeremy Fitzhardinge   hid-input/battery...
367
368
369
370
  	if (quirks & HID_BATTERY_QUIRK_PERCENT) {
  		min = 0;
  		max = 100;
  	}
652aa6a9a   Jeremy Fitzhardinge   hid-input/battery...
371
372
  	if (quirks & HID_BATTERY_QUIRK_FEATURE)
  		report_type = HID_FEATURE_REPORT;
4f5ca836b   Jeremy Fitzhardinge   HID: hid-input: a...
373
374
  	dev->battery_min = min;
  	dev->battery_max = max;
fb8ac91b4   Jeremy Fitzhardinge   hid-input/battery...
375
  	dev->battery_report_type = report_type;
2f2e3f6d7   Jeremy Fitzhardinge   hid-input/battery...
376
  	dev->battery_report_id = field->report->id;
4f5ca836b   Jeremy Fitzhardinge   HID: hid-input: a...
377
378
379
380
381
382
383
384
  
  	ret = power_supply_register(&dev->dev, battery);
  	if (ret != 0) {
  		hid_warn(dev, "can't register power supply: %d
  ", ret);
  		kfree(battery->name);
  		battery->name = NULL;
  	}
2f2e3f6d7   Jeremy Fitzhardinge   hid-input/battery...
385
386
387
  
  out:
  	return true;
4f5ca836b   Jeremy Fitzhardinge   HID: hid-input: a...
388
389
390
391
392
393
394
395
396
397
398
399
  }
  
  static void hidinput_cleanup_battery(struct hid_device *dev)
  {
  	if (!dev->battery.name)
  		return;
  
  	power_supply_unregister(&dev->battery);
  	kfree(dev->battery.name);
  	dev->battery.name = NULL;
  }
  #else  /* !CONFIG_HID_BATTERY_STRENGTH */
2f2e3f6d7   Jeremy Fitzhardinge   hid-input/battery...
400
401
  static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type,
  				   struct hid_field *field)
4f5ca836b   Jeremy Fitzhardinge   HID: hid-input: a...
402
  {
2f2e3f6d7   Jeremy Fitzhardinge   hid-input/battery...
403
  	return false;
4f5ca836b   Jeremy Fitzhardinge   HID: hid-input: a...
404
405
406
407
408
409
  }
  
  static void hidinput_cleanup_battery(struct hid_device *dev)
  {
  }
  #endif	/* CONFIG_HID_BATTERY_STRENGTH */
dde5845a5   Jiri Kosina   [PATCH] Generic H...
410
411
412
413
  static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field,
  				     struct hid_usage *usage)
  {
  	struct input_dev *input = hidinput->input;
e07129858   Dmitry Torokhov   HID: switch to us...
414
  	struct hid_device *device = input_get_drvdata(input);
3715ade98   Jiri Slaby   HID: remove hid-i...
415
  	int max = 0, code;
dde5845a5   Jiri Kosina   [PATCH] Generic H...
416
417
418
  	unsigned long *bit = NULL;
  
  	field->hidinput = hidinput;
dde5845a5   Jiri Kosina   [PATCH] Generic H...
419
420
  	if (field->flags & HID_MAIN_ITEM_CONSTANT)
  		goto ignore;
82eb12198   Jiri Kosina   HID: ignore all n...
421
422
423
  	/* only LED usages are supported in output fields */
  	if (field->report_type == HID_OUTPUT_REPORT &&
  			(usage->hid & HID_USAGE_PAGE) != HID_UP_LED) {
82eb12198   Jiri Kosina   HID: ignore all n...
424
425
  		goto ignore;
  	}
c500c9714   Jiri Slaby   HID: hid, make pa...
426
427
428
429
430
431
432
433
  	if (device->driver->input_mapping) {
  		int ret = device->driver->input_mapping(device, hidinput, field,
  				usage, &bit, &max);
  		if (ret > 0)
  			goto mapped;
  		if (ret < 0)
  			goto ignore;
  	}
dde5845a5   Jiri Kosina   [PATCH] Generic H...
434
  	switch (usage->hid & HID_USAGE_PAGE) {
880d29f10   Jiri Slaby   HID: indent switc...
435
436
  	case HID_UP_UNDEFINED:
  		goto ignore;
dde5845a5   Jiri Kosina   [PATCH] Generic H...
437

880d29f10   Jiri Slaby   HID: indent switc...
438
439
  	case HID_UP_KEYBOARD:
  		set_bit(EV_REP, input->evbit);
dde5845a5   Jiri Kosina   [PATCH] Generic H...
440

880d29f10   Jiri Slaby   HID: indent switc...
441
442
443
444
445
  		if ((usage->hid & HID_USAGE) < 256) {
  			if (!hid_keyboard[usage->hid & HID_USAGE]) goto ignore;
  			map_key_clear(hid_keyboard[usage->hid & HID_USAGE]);
  		} else
  			map_key(KEY_UNKNOWN);
dde5845a5   Jiri Kosina   [PATCH] Generic H...
446

880d29f10   Jiri Slaby   HID: indent switc...
447
  		break;
dde5845a5   Jiri Kosina   [PATCH] Generic H...
448

880d29f10   Jiri Slaby   HID: indent switc...
449
  	case HID_UP_BUTTON:
7f978b9bf   Jiri Kosina   HID: extend mask ...
450
  		code = ((usage->hid - 1) & HID_USAGE);
dde5845a5   Jiri Kosina   [PATCH] Generic H...
451

880d29f10   Jiri Slaby   HID: indent switc...
452
453
  		switch (field->application) {
  		case HID_GD_MOUSE:
1874542d9   Florian Fainelli   HID: replace offs...
454
  		case HID_GD_POINTER:  code += BTN_MOUSE; break;
cf2f765f1   Jiri Kosina   HID: handle joyst...
455
  		case HID_GD_JOYSTICK:
fc99f22c5   Daniel Mack   HID: hid-input.c:...
456
457
458
459
460
  				if (code <= 0xf)
  					code += BTN_JOYSTICK;
  				else
  					code += BTN_TRIGGER_HAPPY;
  				break;
1874542d9   Florian Fainelli   HID: replace offs...
461
  		case HID_GD_GAMEPAD:  code += BTN_GAMEPAD; break;
880d29f10   Jiri Slaby   HID: indent switc...
462
463
464
  		default:
  			switch (field->physical) {
  			case HID_GD_MOUSE:
1874542d9   Florian Fainelli   HID: replace offs...
465
466
467
468
  			case HID_GD_POINTER:  code += BTN_MOUSE; break;
  			case HID_GD_JOYSTICK: code += BTN_JOYSTICK; break;
  			case HID_GD_GAMEPAD:  code += BTN_GAMEPAD; break;
  			default:              code += BTN_MISC;
dde5845a5   Jiri Kosina   [PATCH] Generic H...
469
  			}
880d29f10   Jiri Slaby   HID: indent switc...
470
  		}
dde5845a5   Jiri Kosina   [PATCH] Generic H...
471

880d29f10   Jiri Slaby   HID: indent switc...
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
  		map_key(code);
  		break;
  
  	case HID_UP_SIMULATION:
  		switch (usage->hid & 0xffff) {
  		case 0xba: map_abs(ABS_RUDDER);   break;
  		case 0xbb: map_abs(ABS_THROTTLE); break;
  		case 0xc4: map_abs(ABS_GAS);      break;
  		case 0xc5: map_abs(ABS_BRAKE);    break;
  		case 0xc8: map_abs(ABS_WHEEL);    break;
  		default:   goto ignore;
  		}
  		break;
  
  	case HID_UP_GENDESK:
  		if ((usage->hid & 0xf0) == 0x80) {	/* SystemControl */
  			switch (usage->hid & 0xf) {
  			case 0x1: map_key_clear(KEY_POWER);  break;
  			case 0x2: map_key_clear(KEY_SLEEP);  break;
  			case 0x3: map_key_clear(KEY_WAKEUP); break;
437f3b199   Jarod Wilson   HID: assorted usa...
492
493
494
495
496
497
498
499
500
501
502
503
  			case 0x4: map_key_clear(KEY_CONTEXT_MENU); break;
  			case 0x5: map_key_clear(KEY_MENU); break;
  			case 0x6: map_key_clear(KEY_PROG1); break;
  			case 0x7: map_key_clear(KEY_HELP); break;
  			case 0x8: map_key_clear(KEY_EXIT); break;
  			case 0x9: map_key_clear(KEY_SELECT); break;
  			case 0xa: map_key_clear(KEY_RIGHT); break;
  			case 0xb: map_key_clear(KEY_LEFT); break;
  			case 0xc: map_key_clear(KEY_UP); break;
  			case 0xd: map_key_clear(KEY_DOWN); break;
  			case 0xe: map_key_clear(KEY_POWER2); break;
  			case 0xf: map_key_clear(KEY_RESTART); break;
880d29f10   Jiri Slaby   HID: indent switc...
504
  			default: goto unknown;
dde5845a5   Jiri Kosina   [PATCH] Generic H...
505
506
  			}
  			break;
880d29f10   Jiri Slaby   HID: indent switc...
507
  		}
dde5845a5   Jiri Kosina   [PATCH] Generic H...
508

880d29f10   Jiri Slaby   HID: indent switc...
509
  		if ((usage->hid & 0xf0) == 0x90) {	/* D-pad */
dde5845a5   Jiri Kosina   [PATCH] Generic H...
510
  			switch (usage->hid) {
880d29f10   Jiri Slaby   HID: indent switc...
511
512
513
514
515
  			case HID_GD_UP:	   usage->hat_dir = 1; break;
  			case HID_GD_DOWN:  usage->hat_dir = 5; break;
  			case HID_GD_RIGHT: usage->hat_dir = 3; break;
  			case HID_GD_LEFT:  usage->hat_dir = 7; break;
  			default: goto unknown;
dde5845a5   Jiri Kosina   [PATCH] Generic H...
516
  			}
880d29f10   Jiri Slaby   HID: indent switc...
517
518
519
  			if (field->dpad) {
  				map_abs(field->dpad);
  				goto ignore;
d4ae650a9   Simon Budig   HID: proper LED-m...
520
  			}
880d29f10   Jiri Slaby   HID: indent switc...
521
  			map_abs(ABS_HAT0X);
dde5845a5   Jiri Kosina   [PATCH] Generic H...
522
  			break;
880d29f10   Jiri Slaby   HID: indent switc...
523
  		}
dde5845a5   Jiri Kosina   [PATCH] Generic H...
524

880d29f10   Jiri Slaby   HID: indent switc...
525
526
527
528
529
530
531
532
533
534
  		switch (usage->hid) {
  		/* These usage IDs map directly to the usage codes. */
  		case HID_GD_X: case HID_GD_Y: case HID_GD_Z:
  		case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ:
  		case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL:
  			if (field->flags & HID_MAIN_ITEM_RELATIVE)
  				map_rel(usage->hid & 0xf);
  			else
  				map_abs(usage->hid & 0xf);
  			break;
dde5845a5   Jiri Kosina   [PATCH] Generic H...
535

880d29f10   Jiri Slaby   HID: indent switc...
536
537
538
539
540
  		case HID_GD_HATSWITCH:
  			usage->hat_min = field->logical_minimum;
  			usage->hat_max = field->logical_maximum;
  			map_abs(ABS_HAT0X);
  			break;
dde5845a5   Jiri Kosina   [PATCH] Generic H...
541

880d29f10   Jiri Slaby   HID: indent switc...
542
543
  		case HID_GD_START:	map_key_clear(BTN_START);	break;
  		case HID_GD_SELECT:	map_key_clear(BTN_SELECT);	break;
dde5845a5   Jiri Kosina   [PATCH] Generic H...
544

880d29f10   Jiri Slaby   HID: indent switc...
545
546
  		default: goto unknown;
  		}
dde5845a5   Jiri Kosina   [PATCH] Generic H...
547

880d29f10   Jiri Slaby   HID: indent switc...
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
  		break;
  
  	case HID_UP_LED:
  		switch (usage->hid & 0xffff) {		      /* HID-Value:                   */
  		case 0x01:  map_led (LED_NUML);     break;    /*   "Num Lock"                 */
  		case 0x02:  map_led (LED_CAPSL);    break;    /*   "Caps Lock"                */
  		case 0x03:  map_led (LED_SCROLLL);  break;    /*   "Scroll Lock"              */
  		case 0x04:  map_led (LED_COMPOSE);  break;    /*   "Compose"                  */
  		case 0x05:  map_led (LED_KANA);     break;    /*   "Kana"                     */
  		case 0x27:  map_led (LED_SLEEP);    break;    /*   "Stand-By"                 */
  		case 0x4c:  map_led (LED_SUSPEND);  break;    /*   "System Suspend"           */
  		case 0x09:  map_led (LED_MUTE);     break;    /*   "Mute"                     */
  		case 0x4b:  map_led (LED_MISC);     break;    /*   "Generic Indicator"        */
  		case 0x19:  map_led (LED_MAIL);     break;    /*   "Message Waiting"          */
  		case 0x4d:  map_led (LED_CHARGING); break;    /*   "External Power Connected" */
  
  		default: goto ignore;
  		}
  		break;
  
  	case HID_UP_DIGITIZER:
  		switch (usage->hid & 0xff) {
8c8b01c38   Forest Bond   HID: ignore digit...
570
571
  		case 0x00: /* Undefined */
  			goto ignore;
880d29f10   Jiri Slaby   HID: indent switc...
572
573
574
575
576
  		case 0x30: /* TipPressure */
  			if (!test_bit(BTN_TOUCH, input->keybit)) {
  				device->quirks |= HID_QUIRK_NOTOUCH;
  				set_bit(EV_KEY, input->evbit);
  				set_bit(BTN_TOUCH, input->keybit);
dde5845a5   Jiri Kosina   [PATCH] Generic H...
577
  			}
880d29f10   Jiri Slaby   HID: indent switc...
578
  			map_abs_clear(ABS_PRESSURE);
dde5845a5   Jiri Kosina   [PATCH] Generic H...
579
  			break;
880d29f10   Jiri Slaby   HID: indent switc...
580
581
582
583
584
  		case 0x32: /* InRange */
  			switch (field->physical & 0xff) {
  			case 0x21: map_key(BTN_TOOL_MOUSE); break;
  			case 0x22: map_key(BTN_TOOL_FINGER); break;
  			default: map_key(BTN_TOOL_PEN); break;
dde5845a5   Jiri Kosina   [PATCH] Generic H...
585
586
  			}
  			break;
880d29f10   Jiri Slaby   HID: indent switc...
587
588
  		case 0x3c: /* Invert */
  			map_key_clear(BTN_TOOL_RUBBER);
dde5845a5   Jiri Kosina   [PATCH] Generic H...
589
  			break;
880d29f10   Jiri Slaby   HID: indent switc...
590
591
592
593
594
595
  		case 0x33: /* Touch */
  		case 0x42: /* TipSwitch */
  		case 0x43: /* TipSwitch2 */
  			device->quirks &= ~HID_QUIRK_NOTOUCH;
  			map_key_clear(BTN_TOUCH);
  			break;
dde5845a5   Jiri Kosina   [PATCH] Generic H...
596

880d29f10   Jiri Slaby   HID: indent switc...
597
598
599
  		case 0x44: /* BarrelSwitch */
  			map_key_clear(BTN_STYLUS);
  			break;
dde5845a5   Jiri Kosina   [PATCH] Generic H...
600

50b636976   Nikolai Kondrashov   HID: Add Tablet P...
601
602
603
  		case 0x46: /* TabletPick */
  			map_key_clear(BTN_STYLUS2);
  			break;
b77c3920e   Benjamin Tissoires   HID: add autodete...
604
605
606
  		case 0x51: /* ContactID */
  			device->quirks |= HID_QUIRK_MULTITOUCH;
  			goto unknown;
880d29f10   Jiri Slaby   HID: indent switc...
607
608
609
  		default:  goto unknown;
  		}
  		break;
437f3b199   Jarod Wilson   HID: assorted usa...
610
  	case HID_UP_CONSUMER:	/* USB HUT v1.12, pages 75-84 */
880d29f10   Jiri Slaby   HID: indent switc...
611
612
  		switch (usage->hid & HID_USAGE) {
  		case 0x000: goto ignore;
437f3b199   Jarod Wilson   HID: assorted usa...
613
614
615
  		case 0x030: map_key_clear(KEY_POWER);		break;
  		case 0x031: map_key_clear(KEY_RESTART);		break;
  		case 0x032: map_key_clear(KEY_SLEEP);		break;
880d29f10   Jiri Slaby   HID: indent switc...
616
  		case 0x034: map_key_clear(KEY_SLEEP);		break;
437f3b199   Jarod Wilson   HID: assorted usa...
617
  		case 0x035: map_key_clear(KEY_KBDILLUMTOGGLE);	break;
880d29f10   Jiri Slaby   HID: indent switc...
618
  		case 0x036: map_key_clear(BTN_MISC);		break;
437f3b199   Jarod Wilson   HID: assorted usa...
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
  		case 0x040: map_key_clear(KEY_MENU);		break; /* Menu */
  		case 0x041: map_key_clear(KEY_SELECT);		break; /* Menu Pick */
  		case 0x042: map_key_clear(KEY_UP);		break; /* Menu Up */
  		case 0x043: map_key_clear(KEY_DOWN);		break; /* Menu Down */
  		case 0x044: map_key_clear(KEY_LEFT);		break; /* Menu Left */
  		case 0x045: map_key_clear(KEY_RIGHT);		break; /* Menu Right */
  		case 0x046: map_key_clear(KEY_ESC);		break; /* Menu Escape */
  		case 0x047: map_key_clear(KEY_KPPLUS);		break; /* Menu Value Increase */
  		case 0x048: map_key_clear(KEY_KPMINUS);		break; /* Menu Value Decrease */
  
  		case 0x060: map_key_clear(KEY_INFO);		break; /* Data On Screen */
  		case 0x061: map_key_clear(KEY_SUBTITLE);	break; /* Closed Caption */
  		case 0x063: map_key_clear(KEY_VCR);		break; /* VCR/TV */
  		case 0x065: map_key_clear(KEY_CAMERA);		break; /* Snapshot */
  		case 0x069: map_key_clear(KEY_RED);		break;
  		case 0x06a: map_key_clear(KEY_GREEN);		break;
  		case 0x06b: map_key_clear(KEY_BLUE);		break;
  		case 0x06c: map_key_clear(KEY_YELLOW);		break;
  		case 0x06d: map_key_clear(KEY_ZOOM);		break;
  
  		case 0x082: map_key_clear(KEY_VIDEO_NEXT);	break;
880d29f10   Jiri Slaby   HID: indent switc...
640
  		case 0x083: map_key_clear(KEY_LAST);		break;
437f3b199   Jarod Wilson   HID: assorted usa...
641
  		case 0x084: map_key_clear(KEY_ENTER);		break;
880d29f10   Jiri Slaby   HID: indent switc...
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
  		case 0x088: map_key_clear(KEY_PC);		break;
  		case 0x089: map_key_clear(KEY_TV);		break;
  		case 0x08a: map_key_clear(KEY_WWW);		break;
  		case 0x08b: map_key_clear(KEY_DVD);		break;
  		case 0x08c: map_key_clear(KEY_PHONE);		break;
  		case 0x08d: map_key_clear(KEY_PROGRAM);		break;
  		case 0x08e: map_key_clear(KEY_VIDEOPHONE);	break;
  		case 0x08f: map_key_clear(KEY_GAMES);		break;
  		case 0x090: map_key_clear(KEY_MEMO);		break;
  		case 0x091: map_key_clear(KEY_CD);		break;
  		case 0x092: map_key_clear(KEY_VCR);		break;
  		case 0x093: map_key_clear(KEY_TUNER);		break;
  		case 0x094: map_key_clear(KEY_EXIT);		break;
  		case 0x095: map_key_clear(KEY_HELP);		break;
  		case 0x096: map_key_clear(KEY_TAPE);		break;
  		case 0x097: map_key_clear(KEY_TV2);		break;
  		case 0x098: map_key_clear(KEY_SAT);		break;
  		case 0x09a: map_key_clear(KEY_PVR);		break;
  
  		case 0x09c: map_key_clear(KEY_CHANNELUP);	break;
  		case 0x09d: map_key_clear(KEY_CHANNELDOWN);	break;
  		case 0x0a0: map_key_clear(KEY_VCR2);		break;
  
  		case 0x0b0: map_key_clear(KEY_PLAY);		break;
  		case 0x0b1: map_key_clear(KEY_PAUSE);		break;
  		case 0x0b2: map_key_clear(KEY_RECORD);		break;
  		case 0x0b3: map_key_clear(KEY_FASTFORWARD);	break;
  		case 0x0b4: map_key_clear(KEY_REWIND);		break;
  		case 0x0b5: map_key_clear(KEY_NEXTSONG);	break;
  		case 0x0b6: map_key_clear(KEY_PREVIOUSSONG);	break;
  		case 0x0b7: map_key_clear(KEY_STOPCD);		break;
  		case 0x0b8: map_key_clear(KEY_EJECTCD);		break;
  		case 0x0bc: map_key_clear(KEY_MEDIA_REPEAT);	break;
437f3b199   Jarod Wilson   HID: assorted usa...
675
676
  		case 0x0b9: map_key_clear(KEY_SHUFFLE);		break;
  		case 0x0bf: map_key_clear(KEY_SLOW);		break;
880d29f10   Jiri Slaby   HID: indent switc...
677
678
679
680
681
682
683
  
  		case 0x0cd: map_key_clear(KEY_PLAYPAUSE);	break;
  		case 0x0e0: map_abs_clear(ABS_VOLUME);		break;
  		case 0x0e2: map_key_clear(KEY_MUTE);		break;
  		case 0x0e5: map_key_clear(KEY_BASSBOOST);	break;
  		case 0x0e9: map_key_clear(KEY_VOLUMEUP);	break;
  		case 0x0ea: map_key_clear(KEY_VOLUMEDOWN);	break;
437f3b199   Jarod Wilson   HID: assorted usa...
684
  		case 0x0f5: map_key_clear(KEY_SLOW);		break;
880d29f10   Jiri Slaby   HID: indent switc...
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
  
  		case 0x182: map_key_clear(KEY_BOOKMARKS);	break;
  		case 0x183: map_key_clear(KEY_CONFIG);		break;
  		case 0x184: map_key_clear(KEY_WORDPROCESSOR);	break;
  		case 0x185: map_key_clear(KEY_EDITOR);		break;
  		case 0x186: map_key_clear(KEY_SPREADSHEET);	break;
  		case 0x187: map_key_clear(KEY_GRAPHICSEDITOR);	break;
  		case 0x188: map_key_clear(KEY_PRESENTATION);	break;
  		case 0x189: map_key_clear(KEY_DATABASE);	break;
  		case 0x18a: map_key_clear(KEY_MAIL);		break;
  		case 0x18b: map_key_clear(KEY_NEWS);		break;
  		case 0x18c: map_key_clear(KEY_VOICEMAIL);	break;
  		case 0x18d: map_key_clear(KEY_ADDRESSBOOK);	break;
  		case 0x18e: map_key_clear(KEY_CALENDAR);	break;
  		case 0x191: map_key_clear(KEY_FINANCE);		break;
  		case 0x192: map_key_clear(KEY_CALC);		break;
437f3b199   Jarod Wilson   HID: assorted usa...
701
  		case 0x193: map_key_clear(KEY_PLAYER);		break;
880d29f10   Jiri Slaby   HID: indent switc...
702
703
  		case 0x194: map_key_clear(KEY_FILE);		break;
  		case 0x196: map_key_clear(KEY_WWW);		break;
0690535d6   Leo P White   HID: add mapping ...
704
  		case 0x199: map_key_clear(KEY_CHAT);		break;
880d29f10   Jiri Slaby   HID: indent switc...
705
706
707
708
709
  		case 0x19c: map_key_clear(KEY_LOGOFF);		break;
  		case 0x19e: map_key_clear(KEY_COFFEE);		break;
  		case 0x1a6: map_key_clear(KEY_HELP);		break;
  		case 0x1a7: map_key_clear(KEY_DOCUMENTS);	break;
  		case 0x1ab: map_key_clear(KEY_SPELLCHECK);	break;
437f3b199   Jarod Wilson   HID: assorted usa...
710
711
712
713
  		case 0x1ae: map_key_clear(KEY_KEYBOARD);	break;
  		case 0x1b6: map_key_clear(KEY_IMAGES);		break;
  		case 0x1b7: map_key_clear(KEY_AUDIO);		break;
  		case 0x1b8: map_key_clear(KEY_VIDEO);		break;
880d29f10   Jiri Slaby   HID: indent switc...
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
  		case 0x1bc: map_key_clear(KEY_MESSENGER);	break;
  		case 0x1bd: map_key_clear(KEY_INFO);		break;
  		case 0x201: map_key_clear(KEY_NEW);		break;
  		case 0x202: map_key_clear(KEY_OPEN);		break;
  		case 0x203: map_key_clear(KEY_CLOSE);		break;
  		case 0x204: map_key_clear(KEY_EXIT);		break;
  		case 0x207: map_key_clear(KEY_SAVE);		break;
  		case 0x208: map_key_clear(KEY_PRINT);		break;
  		case 0x209: map_key_clear(KEY_PROPS);		break;
  		case 0x21a: map_key_clear(KEY_UNDO);		break;
  		case 0x21b: map_key_clear(KEY_COPY);		break;
  		case 0x21c: map_key_clear(KEY_CUT);		break;
  		case 0x21d: map_key_clear(KEY_PASTE);		break;
  		case 0x21f: map_key_clear(KEY_FIND);		break;
  		case 0x221: map_key_clear(KEY_SEARCH);		break;
  		case 0x222: map_key_clear(KEY_GOTO);		break;
  		case 0x223: map_key_clear(KEY_HOMEPAGE);	break;
  		case 0x224: map_key_clear(KEY_BACK);		break;
  		case 0x225: map_key_clear(KEY_FORWARD);		break;
  		case 0x226: map_key_clear(KEY_STOP);		break;
  		case 0x227: map_key_clear(KEY_REFRESH);		break;
  		case 0x22a: map_key_clear(KEY_BOOKMARKS);	break;
  		case 0x22d: map_key_clear(KEY_ZOOMIN);		break;
  		case 0x22e: map_key_clear(KEY_ZOOMOUT);		break;
  		case 0x22f: map_key_clear(KEY_ZOOMRESET);	break;
  		case 0x233: map_key_clear(KEY_SCROLLUP);	break;
  		case 0x234: map_key_clear(KEY_SCROLLDOWN);	break;
  		case 0x238: map_rel(REL_HWHEEL);		break;
437f3b199   Jarod Wilson   HID: assorted usa...
742
  		case 0x23d: map_key_clear(KEY_EDIT);		break;
880d29f10   Jiri Slaby   HID: indent switc...
743
  		case 0x25f: map_key_clear(KEY_CANCEL);		break;
437f3b199   Jarod Wilson   HID: assorted usa...
744
745
  		case 0x269: map_key_clear(KEY_INSERT);		break;
  		case 0x26a: map_key_clear(KEY_DELETE);		break;
880d29f10   Jiri Slaby   HID: indent switc...
746
747
748
749
750
751
752
753
754
  		case 0x279: map_key_clear(KEY_REDO);		break;
  
  		case 0x289: map_key_clear(KEY_REPLY);		break;
  		case 0x28b: map_key_clear(KEY_FORWARDMAIL);	break;
  		case 0x28c: map_key_clear(KEY_SEND);		break;
  
  		default:    goto ignore;
  		}
  		break;
4f5ca836b   Jeremy Fitzhardinge   HID: hid-input: a...
755
  	case HID_UP_GENDEVCTRLS:
2f2e3f6d7   Jeremy Fitzhardinge   hid-input/battery...
756
  		if (hidinput_setup_battery(device, HID_INPUT_REPORT, field))
4f5ca836b   Jeremy Fitzhardinge   HID: hid-input: a...
757
  			goto ignore;
2f2e3f6d7   Jeremy Fitzhardinge   hid-input/battery...
758
  		else
4f5ca836b   Jeremy Fitzhardinge   HID: hid-input: a...
759
760
  			goto unknown;
  		break;
880d29f10   Jiri Slaby   HID: indent switc...
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
  	case HID_UP_HPVENDOR:	/* Reported on a Dutch layout HP5308 */
  		set_bit(EV_REP, input->evbit);
  		switch (usage->hid & HID_USAGE) {
  		case 0x021: map_key_clear(KEY_PRINT);           break;
  		case 0x070: map_key_clear(KEY_HP);		break;
  		case 0x071: map_key_clear(KEY_CAMERA);		break;
  		case 0x072: map_key_clear(KEY_SOUND);		break;
  		case 0x073: map_key_clear(KEY_QUESTION);	break;
  		case 0x080: map_key_clear(KEY_EMAIL);		break;
  		case 0x081: map_key_clear(KEY_CHAT);		break;
  		case 0x082: map_key_clear(KEY_SEARCH);		break;
  		case 0x083: map_key_clear(KEY_CONNECT);	        break;
  		case 0x084: map_key_clear(KEY_FINANCE);		break;
  		case 0x085: map_key_clear(KEY_SPORT);		break;
  		case 0x086: map_key_clear(KEY_SHOP);	        break;
  		default:    goto ignore;
  		}
  		break;
dde5845a5   Jiri Kosina   [PATCH] Generic H...
779

880d29f10   Jiri Slaby   HID: indent switc...
780
781
  	case HID_UP_MSVENDOR:
  		goto ignore;
dde5845a5   Jiri Kosina   [PATCH] Generic H...
782

880d29f10   Jiri Slaby   HID: indent switc...
783
784
785
  	case HID_UP_CUSTOM: /* Reported on Logitech and Apple USB keyboards */
  		set_bit(EV_REP, input->evbit);
  		goto ignore;
dde5845a5   Jiri Kosina   [PATCH] Generic H...
786

880d29f10   Jiri Slaby   HID: indent switc...
787
788
  	case HID_UP_LOGIVENDOR:
  		goto ignore;
fc99f22c5   Daniel Mack   HID: hid-input.c:...
789

880d29f10   Jiri Slaby   HID: indent switc...
790
791
792
793
794
795
  	case HID_UP_PID:
  		switch (usage->hid & HID_USAGE) {
  		case 0xa4: map_key_clear(BTN_DEAD);	break;
  		default: goto ignore;
  		}
  		break;
dde5845a5   Jiri Kosina   [PATCH] Generic H...
796

880d29f10   Jiri Slaby   HID: indent switc...
797
798
799
800
801
  	default:
  	unknown:
  		if (field->report_size == 1) {
  			if (field->report->type == HID_OUTPUT_REPORT) {
  				map_led(LED_MISC);
dde5845a5   Jiri Kosina   [PATCH] Generic H...
802
803
  				break;
  			}
880d29f10   Jiri Slaby   HID: indent switc...
804
  			map_key(BTN_MISC);
dde5845a5   Jiri Kosina   [PATCH] Generic H...
805
  			break;
880d29f10   Jiri Slaby   HID: indent switc...
806
807
808
809
810
811
812
  		}
  		if (field->flags & HID_MAIN_ITEM_RELATIVE) {
  			map_rel(REL_MISC);
  			break;
  		}
  		map_abs(ABS_MISC);
  		break;
dde5845a5   Jiri Kosina   [PATCH] Generic H...
813
  	}
10bd065fa   Jiri Kosina   HID: refactor map...
814
  mapped:
c500c9714   Jiri Slaby   HID: hid, make pa...
815
816
817
  	if (device->driver->input_mapped && device->driver->input_mapped(device,
  				hidinput, field, usage, &bit, &max) < 0)
  		goto ignore;
dde5845a5   Jiri Kosina   [PATCH] Generic H...
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
  	set_bit(usage->type, input->evbit);
  
  	while (usage->code <= max && test_and_set_bit(usage->code, bit))
  		usage->code = find_next_zero_bit(bit, max + 1, usage->code);
  
  	if (usage->code > max)
  		goto ignore;
  
  
  	if (usage->type == EV_ABS) {
  
  		int a = field->logical_minimum;
  		int b = field->logical_maximum;
  
  		if ((device->quirks & HID_QUIRK_BADPAD) && (usage->code == ABS_X || usage->code == ABS_Y)) {
  			a = field->logical_minimum = 0;
  			b = field->logical_maximum = 255;
  		}
  
  		if (field->application == HID_GD_GAMEPAD || field->application == HID_GD_JOYSTICK)
  			input_set_abs_params(input, usage->code, a, b, (b - a) >> 8, (b - a) >> 4);
  		else	input_set_abs_params(input, usage->code, a, b, 0, 0);
4ea6e4ffb   Nikolai Kondrashov   HID: add absolute...
840
841
  		input_abs_set_res(input, usage->code,
  				  hidinput_calc_abs_res(field, usage->code));
6967b4d9d   Henrik Rydberg   Input: hid-input ...
842
843
844
  		/* use a larger default input buffer for MT devices */
  		if (usage->code == ABS_MT_POSITION_X && input->hint_events_per_packet == 0)
  			input_set_events_per_packet(input, 60);
dde5845a5   Jiri Kosina   [PATCH] Generic H...
845
846
847
848
849
850
851
852
853
854
855
856
  	}
  
  	if (usage->type == EV_ABS &&
  	    (usage->hat_min < usage->hat_max || usage->hat_dir)) {
  		int i;
  		for (i = usage->code; i < usage->code + 2 && i <= max; i++) {
  			input_set_abs_params(input, i, -1, 1, 0, 0);
  			set_bit(i, input->absbit);
  		}
  		if (usage->hat_dir && !field->dpad)
  			field->dpad = usage->code;
  	}
2c1d8aea2   Jiri Kosina   HID: handle cases...
857
858
859
860
861
862
863
864
865
  	/* 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);
  	}
c01d50d18   Jiri Kosina   HID: Report usage...
866
867
868
869
  	if (usage->type == EV_KEY) {
  		set_bit(EV_MSC, input->evbit);
  		set_bit(MSC_SCAN, input->mscbit);
  	}
dde5845a5   Jiri Kosina   [PATCH] Generic H...
870
  ignore:
dde5845a5   Jiri Kosina   [PATCH] Generic H...
871
  	return;
a635f9dd8   Jiri Kosina   HID: use debugfs ...
872

dde5845a5   Jiri Kosina   [PATCH] Generic H...
873
874
875
876
877
  }
  
  void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value)
  {
  	struct input_dev *input;
b4482a4b2   Al Viro   more trivial sign...
878
  	unsigned *quirks = &hid->quirks;
dde5845a5   Jiri Kosina   [PATCH] Generic H...
879
880
881
882
883
884
885
886
  
  	if (!field->hidinput)
  		return;
  
  	input = field->hidinput->input;
  
  	if (!usage->type)
  		return;
dde5845a5   Jiri Kosina   [PATCH] Generic H...
887
888
889
890
891
892
  	if (usage->hat_min < usage->hat_max || usage->hat_dir) {
  		int hat_dir = usage->hat_dir;
  		if (!hat_dir)
  			hat_dir = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1;
  		if (hat_dir < 0 || hat_dir > 8) hat_dir = 0;
  		input_event(input, usage->type, usage->code    , hid_hat_to_axis[hat_dir].x);
fc99f22c5   Daniel Mack   HID: hid-input.c:...
893
894
895
  		input_event(input, usage->type, usage->code + 1, hid_hat_to_axis[hat_dir].y);
  		return;
  	}
dde5845a5   Jiri Kosina   [PATCH] Generic H...
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
  
  	if (usage->hid == (HID_UP_DIGITIZER | 0x003c)) { /* Invert */
  		*quirks = value ? (*quirks | HID_QUIRK_INVERT) : (*quirks & ~HID_QUIRK_INVERT);
  		return;
  	}
  
  	if (usage->hid == (HID_UP_DIGITIZER | 0x0032)) { /* InRange */
  		if (value) {
  			input_event(input, usage->type, (*quirks & HID_QUIRK_INVERT) ? BTN_TOOL_RUBBER : usage->code, 1);
  			return;
  		}
  		input_event(input, usage->type, usage->code, 0);
  		input_event(input, usage->type, BTN_TOOL_RUBBER, 0);
  		return;
  	}
  
  	if (usage->hid == (HID_UP_DIGITIZER | 0x0030) && (*quirks & HID_QUIRK_NOTOUCH)) { /* Pressure */
  		int a = field->logical_minimum;
  		int b = field->logical_maximum;
  		input_event(input, EV_KEY, BTN_TOUCH, value > a + ((b - a) >> 3));
  	}
  
  	if (usage->hid == (HID_UP_PID | 0x83UL)) { /* Simultaneous Effects Max */
58037eb96   Jiri Kosina   HID: make debuggi...
919
920
  		dbg_hid("Maximum Effects - %d
  ",value);
dde5845a5   Jiri Kosina   [PATCH] Generic H...
921
922
923
924
  		return;
  	}
  
  	if (usage->hid == (HID_UP_PID | 0x7fUL)) {
58037eb96   Jiri Kosina   HID: make debuggi...
925
926
  		dbg_hid("PID Pool Report
  ");
dde5845a5   Jiri Kosina   [PATCH] Generic H...
927
928
929
930
931
  		return;
  	}
  
  	if ((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */
  		return;
2c1d8aea2   Jiri Kosina   HID: handle cases...
932
933
934
935
936
937
938
939
940
941
942
943
944
945
  	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;
  	}
b4b583d4e   Jiri Kosina   HID: be more stri...
946
947
  	/* Ignore out-of-range values as per HID specification, section 5.10 */
  	if (value < field->logical_minimum || value > field->logical_maximum) {
6da706690   Jiri Kosina   HID: ignore absol...
948
949
950
951
  		dbg_hid("Ignoring out-of-range value %x
  ", value);
  		return;
  	}
c01d50d18   Jiri Kosina   HID: Report usage...
952
953
954
  	/* report the usage code as scancode if the key status has changed */
  	if (usage->type == EV_KEY && !!test_bit(usage->code, input->key) != value)
  		input_event(input, EV_MSC, MSC_SCAN, usage->hid);
1fe8736da   Jiri Kosina   HID: add support ...
955

dde5845a5   Jiri Kosina   [PATCH] Generic H...
956
957
958
959
960
961
962
963
964
  	input_event(input, usage->type, usage->code, value);
  
  	if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY))
  		input_event(input, usage->type, usage->code, 0);
  }
  
  void hidinput_report_event(struct hid_device *hid, struct hid_report *report)
  {
  	struct hid_input *hidinput;
24750f3e4   Henrik Rydberg   HID: Add a hid qu...
965
966
  	if (hid->quirks & HID_QUIRK_NO_INPUT_SYNC)
  		return;
dde5845a5   Jiri Kosina   [PATCH] Generic H...
967
968
969
  	list_for_each_entry(hidinput, &hid->inputs, list)
  		input_sync(hidinput->input);
  }
229695e51   Jiri Kosina   [PATCH] Generic H...
970
  EXPORT_SYMBOL_GPL(hidinput_report_event);
dde5845a5   Jiri Kosina   [PATCH] Generic H...
971

229695e51   Jiri Kosina   [PATCH] Generic H...
972
  int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field)
dde5845a5   Jiri Kosina   [PATCH] Generic H...
973
974
975
976
977
978
979
980
981
982
983
984
985
986
  {
  	struct hid_report *report;
  	int i, j;
  
  	list_for_each_entry(report, &hid->report_enum[HID_OUTPUT_REPORT].report_list, list) {
  		for (i = 0; i < report->maxfield; i++) {
  			*field = report->field[i];
  			for (j = 0; j < (*field)->maxusage; j++)
  				if ((*field)->usage[j].type == type && (*field)->usage[j].code == code)
  					return j;
  		}
  	}
  	return -1;
  }
229695e51   Jiri Kosina   [PATCH] Generic H...
987
  EXPORT_SYMBOL_GPL(hidinput_find_field);
dde5845a5   Jiri Kosina   [PATCH] Generic H...
988

4371ea820   Daniel Kurtz   HID: usbhid: defe...
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
  struct hid_field *hidinput_get_led_field(struct hid_device *hid)
  {
  	struct hid_report *report;
  	struct hid_field *field;
  	int i, j;
  
  	list_for_each_entry(report,
  			    &hid->report_enum[HID_OUTPUT_REPORT].report_list,
  			    list) {
  		for (i = 0; i < report->maxfield; i++) {
  			field = report->field[i];
  			for (j = 0; j < field->maxusage; j++)
  				if (field->usage[j].type == EV_LED)
  					return field;
  		}
  	}
  	return NULL;
  }
  EXPORT_SYMBOL_GPL(hidinput_get_led_field);
  
  unsigned int hidinput_count_leds(struct hid_device *hid)
  {
  	struct hid_report *report;
  	struct hid_field *field;
  	int i, j;
  	unsigned int count = 0;
  
  	list_for_each_entry(report,
  			    &hid->report_enum[HID_OUTPUT_REPORT].report_list,
  			    list) {
  		for (i = 0; i < report->maxfield; i++) {
  			field = report->field[i];
  			for (j = 0; j < field->maxusage; j++)
  				if (field->usage[j].type == EV_LED &&
  				    field->value[j])
  					count += 1;
  		}
  	}
  	return count;
  }
  EXPORT_SYMBOL_GPL(hidinput_count_leds);
7c3791460   Jiri Kosina   HID: API - fix le...
1030
1031
  static int hidinput_open(struct input_dev *dev)
  {
e07129858   Dmitry Torokhov   HID: switch to us...
1032
  	struct hid_device *hid = input_get_drvdata(dev);
5bea7660b   Dmitry Torokhov   HID: add hid_hw_o...
1033
  	return hid_hw_open(hid);
7c3791460   Jiri Kosina   HID: API - fix le...
1034
1035
1036
1037
  }
  
  static void hidinput_close(struct input_dev *dev)
  {
e07129858   Dmitry Torokhov   HID: switch to us...
1038
  	struct hid_device *hid = input_get_drvdata(dev);
5bea7660b   Dmitry Torokhov   HID: add hid_hw_o...
1039
  	hid_hw_close(hid);
7c3791460   Jiri Kosina   HID: API - fix le...
1040
  }
f635bd11c   Henrik Rydberg   HID: Do not creat...
1041
1042
1043
1044
1045
1046
  static void report_features(struct hid_device *hid)
  {
  	struct hid_driver *drv = hid->driver;
  	struct hid_report_enum *rep_enum;
  	struct hid_report *rep;
  	int i, j;
f635bd11c   Henrik Rydberg   HID: Do not creat...
1047
1048
1049
  	rep_enum = &hid->report_enum[HID_FEATURE_REPORT];
  	list_for_each_entry(rep, &rep_enum->report_list, list)
  		for (i = 0; i < rep->maxfield; i++)
c5a92aa3e   Daniel Nicoletti   hid-input: add su...
1050
1051
  			for (j = 0; j < rep->field[i]->maxusage; j++) {
  				/* Verify if Battery Strength feature is available */
2f2e3f6d7   Jeremy Fitzhardinge   hid-input/battery...
1052
  				hidinput_setup_battery(hid, HID_FEATURE_REPORT, rep->field[i]);
c5a92aa3e   Daniel Nicoletti   hid-input: add su...
1053
1054
1055
1056
1057
  
  				if (drv->feature_mapping)
  					drv->feature_mapping(hid, rep->field[i],
  							     rep->field[i]->usage + j);
  			}
f635bd11c   Henrik Rydberg   HID: Do not creat...
1058
  }
dde5845a5   Jiri Kosina   [PATCH] Generic H...
1059
1060
1061
1062
1063
  /*
   * Register the input device; print a message.
   * Configure the input layer interface
   * Read all reports and initialize the absolute field values.
   */
93c10132a   Jiri Slaby   HID: move connect...
1064
  int hidinput_connect(struct hid_device *hid, unsigned int force)
dde5845a5   Jiri Kosina   [PATCH] Generic H...
1065
  {
dde5845a5   Jiri Kosina   [PATCH] Generic H...
1066
1067
1068
1069
1070
1071
  	struct hid_report *report;
  	struct hid_input *hidinput = NULL;
  	struct input_dev *input_dev;
  	int i, j, k;
  
  	INIT_LIST_HEAD(&hid->inputs);
93c10132a   Jiri Slaby   HID: move connect...
1072
1073
1074
1075
1076
1077
1078
1079
  	if (!force) {
  		for (i = 0; i < hid->maxcollection; i++) {
  			struct hid_collection *col = &hid->collection[i];
  			if (col->type == HID_COLLECTION_APPLICATION ||
  					col->type == HID_COLLECTION_PHYSICAL)
  				if (IS_INPUT_APPLICATION(col->usage))
  					break;
  		}
dde5845a5   Jiri Kosina   [PATCH] Generic H...
1080

93c10132a   Jiri Slaby   HID: move connect...
1081
1082
1083
  		if (i == hid->maxcollection)
  			return -1;
  	}
dde5845a5   Jiri Kosina   [PATCH] Generic H...
1084

f635bd11c   Henrik Rydberg   HID: Do not creat...
1085
1086
1087
  	report_features(hid);
  
  	for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
0d2689c0f   Benjamin Tissoires   HID: add feature_...
1088
1089
1090
  		if (k == HID_OUTPUT_REPORT &&
  			hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
  			continue;
5556feae1   Anssi Hannula   hid: quirk for mu...
1091

dde5845a5   Jiri Kosina   [PATCH] Generic H...
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
  		list_for_each_entry(report, &hid->report_enum[k].report_list, list) {
  
  			if (!report->maxfield)
  				continue;
  
  			if (!hidinput) {
  				hidinput = kzalloc(sizeof(*hidinput), GFP_KERNEL);
  				input_dev = input_allocate_device();
  				if (!hidinput || !input_dev) {
  					kfree(hidinput);
  					input_free_device(input_dev);
4291ee305   Joe Perches   HID: Add and use ...
1103
1104
  					hid_err(hid, "Out of memory during hid input probe
  ");
368d290ba   Dirk Hohndel   HID: fix hidinput...
1105
  					goto out_unwind;
dde5845a5   Jiri Kosina   [PATCH] Generic H...
1106
  				}
e07129858   Dmitry Torokhov   HID: switch to us...
1107
  				input_set_drvdata(input_dev, hid);
c500c9714   Jiri Slaby   HID: hid, make pa...
1108
1109
  				input_dev->event =
  					hid->ll_driver->hidinput_input_event;
7c3791460   Jiri Kosina   HID: API - fix le...
1110
1111
  				input_dev->open = hidinput_open;
  				input_dev->close = hidinput_close;
aebd636bd   Dmitry Torokhov   Input: switch com...
1112
1113
  				input_dev->setkeycode = hidinput_setkeycode;
  				input_dev->getkeycode = hidinput_getkeycode;
dde5845a5   Jiri Kosina   [PATCH] Generic H...
1114
1115
1116
1117
  
  				input_dev->name = hid->name;
  				input_dev->phys = hid->phys;
  				input_dev->uniq = hid->uniq;
229695e51   Jiri Kosina   [PATCH] Generic H...
1118
1119
1120
1121
  				input_dev->id.bustype = hid->bus;
  				input_dev->id.vendor  = hid->vendor;
  				input_dev->id.product = hid->product;
  				input_dev->id.version = hid->version;
85cdaf524   Jiri Slaby   HID: make a bus f...
1122
  				input_dev->dev.parent = hid->dev.parent;
dde5845a5   Jiri Kosina   [PATCH] Generic H...
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
  				hidinput->input = input_dev;
  				list_add_tail(&hidinput->list, &hid->inputs);
  			}
  
  			for (i = 0; i < report->maxfield; i++)
  				for (j = 0; j < report->field[i]->maxusage; j++)
  					hidinput_configure_usage(hidinput, report->field[i],
  								 report->field[i]->usage + j);
  
  			if (hid->quirks & HID_QUIRK_MULTI_INPUT) {
  				/* This will leave hidinput NULL, so that it
  				 * allocates another one if we have more inputs on
  				 * the same interface. Some devices (e.g. Happ's
  				 * UGCI) cram a lot of unrelated inputs into the
  				 * same interface. */
  				hidinput->report = report;
368d290ba   Dirk Hohndel   HID: fix hidinput...
1139
1140
  				if (input_register_device(hidinput->input))
  					goto out_cleanup;
dde5845a5   Jiri Kosina   [PATCH] Generic H...
1141
1142
1143
  				hidinput = NULL;
  			}
  		}
0d2689c0f   Benjamin Tissoires   HID: add feature_...
1144
  	}
dde5845a5   Jiri Kosina   [PATCH] Generic H...
1145

b77c3920e   Benjamin Tissoires   HID: add autodete...
1146
1147
1148
1149
1150
1151
  	if (hid->quirks & HID_QUIRK_MULTITOUCH) {
  		/* generic hid does not know how to handle multitouch devices */
  		if (hidinput)
  			goto out_cleanup;
  		goto out_unwind;
  	}
368d290ba   Dirk Hohndel   HID: fix hidinput...
1152
1153
  	if (hidinput && input_register_device(hidinput->input))
  		goto out_cleanup;
dde5845a5   Jiri Kosina   [PATCH] Generic H...
1154
1155
  
  	return 0;
368d290ba   Dirk Hohndel   HID: fix hidinput...
1156
1157
  
  out_cleanup:
d9236303d   Benjamin Tissoires   HID: kernel oops ...
1158
  	list_del(&hidinput->list);
368d290ba   Dirk Hohndel   HID: fix hidinput...
1159
1160
1161
1162
1163
1164
1165
  	input_free_device(hidinput->input);
  	kfree(hidinput);
  out_unwind:
  	/* unwind the ones we already registered */
  	hidinput_disconnect(hid);
  
  	return -1;
dde5845a5   Jiri Kosina   [PATCH] Generic H...
1166
  }
229695e51   Jiri Kosina   [PATCH] Generic H...
1167
  EXPORT_SYMBOL_GPL(hidinput_connect);
dde5845a5   Jiri Kosina   [PATCH] Generic H...
1168
1169
1170
1171
  
  void hidinput_disconnect(struct hid_device *hid)
  {
  	struct hid_input *hidinput, *next;
4f5ca836b   Jeremy Fitzhardinge   HID: hid-input: a...
1172
  	hidinput_cleanup_battery(hid);
dde5845a5   Jiri Kosina   [PATCH] Generic H...
1173
1174
1175
1176
1177
1178
  	list_for_each_entry_safe(hidinput, next, &hid->inputs, list) {
  		list_del(&hidinput->list);
  		input_unregister_device(hidinput->input);
  		kfree(hidinput);
  	}
  }
229695e51   Jiri Kosina   [PATCH] Generic H...
1179
  EXPORT_SYMBOL_GPL(hidinput_disconnect);