Blame view

drivers/input/input.c 52.3 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
  /*
   * The input core
   *
   * Copyright (c) 1999-2002 Vojtech Pavlik
   */
  
  /*
   * This program is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 as published by
   * the Free Software Foundation.
   */
da0c49011   Joe Perches   Input: use pr_fmt...
12
  #define pr_fmt(fmt) KBUILD_BASENAME ": " fmt
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
  #include <linux/init.h>
ffd0db971   Dmitry Torokhov   Input: add generi...
14
  #include <linux/types.h>
47c78e891   Henrik Rydberg   input: mt: Break ...
15
  #include <linux/input/mt.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
  #include <linux/module.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
17
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
19
20
  #include <linux/random.h>
  #include <linux/major.h>
  #include <linux/proc_fs.h>
a99bbaf5e   Alexey Dobriyan   headers: remove s...
21
  #include <linux/sched.h>
969b21cde   Dmitry Torokhov   Input: convert /p...
22
  #include <linux/seq_file.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
24
  #include <linux/poll.h>
  #include <linux/device.h>
e676c232e   Jes Sorensen   Input: input core...
25
  #include <linux/mutex.h>
8006479c9   Dmitry Torokhov   Input: implement ...
26
  #include <linux/rcupdate.h>
15e184afa   Dmitry Torokhov   Input: add compat...
27
  #include "input-compat.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
29
30
31
  
  MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
  MODULE_DESCRIPTION("Input core");
  MODULE_LICENSE("GPL");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
34
35
  #define INPUT_DEVICES	256
  
  static LIST_HEAD(input_dev_list);
  static LIST_HEAD(input_handler_list);
8006479c9   Dmitry Torokhov   Input: implement ...
36
37
38
39
40
41
42
  /*
   * input_mutex protects access to both input_dev_list and input_handler_list.
   * This also causes input_[un]register_device and input_[un]register_handler
   * be mutually exclusive which simplifies locking in drivers implementing
   * input handlers.
   */
  static DEFINE_MUTEX(input_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
  static struct input_handler *input_table[8];
8006479c9   Dmitry Torokhov   Input: implement ...
44
45
  static inline int is_event_supported(unsigned int code,
  				     unsigned long *bm, unsigned int max)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
  {
8006479c9   Dmitry Torokhov   Input: implement ...
47
48
  	return code <= max && test_bit(code, bm);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49

8006479c9   Dmitry Torokhov   Input: implement ...
50
51
52
53
54
  static int input_defuzz_abs_event(int value, int old_val, int fuzz)
  {
  	if (fuzz) {
  		if (value > old_val - fuzz / 2 && value < old_val + fuzz / 2)
  			return old_val;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55

8006479c9   Dmitry Torokhov   Input: implement ...
56
57
  		if (value > old_val - fuzz && value < old_val + fuzz)
  			return (old_val * 3 + value) / 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58

8006479c9   Dmitry Torokhov   Input: implement ...
59
60
61
  		if (value > old_val - fuzz * 2 && value < old_val + fuzz * 2)
  			return (old_val + value) / 2;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62

8006479c9   Dmitry Torokhov   Input: implement ...
63
64
  	return value;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65

8006479c9   Dmitry Torokhov   Input: implement ...
66
  /*
ef7995f4e   Dmitry Torokhov   Input: implement ...
67
68
   * Pass event first through all filters and then, if event has not been
   * filtered out, through all open handles. This function is called with
82ba56c27   Dmitry Torokhov   Input: use full R...
69
   * dev->event_lock held and interrupts disabled.
8006479c9   Dmitry Torokhov   Input: implement ...
70
71
72
73
   */
  static void input_pass_event(struct input_dev *dev,
  			     unsigned int type, unsigned int code, int value)
  {
ef7995f4e   Dmitry Torokhov   Input: implement ...
74
  	struct input_handler *handler;
82ba56c27   Dmitry Torokhov   Input: use full R...
75
76
77
  	struct input_handle *handle;
  
  	rcu_read_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78

82ba56c27   Dmitry Torokhov   Input: use full R...
79
  	handle = rcu_dereference(dev->grab);
8006479c9   Dmitry Torokhov   Input: implement ...
80
81
  	if (handle)
  		handle->handler->event(handle, type, code, value);
ef7995f4e   Dmitry Torokhov   Input: implement ...
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
  	else {
  		bool filtered = false;
  
  		list_for_each_entry_rcu(handle, &dev->h_list, d_node) {
  			if (!handle->open)
  				continue;
  
  			handler = handle->handler;
  			if (!handler->filter) {
  				if (filtered)
  					break;
  
  				handler->event(handle, type, code, value);
  
  			} else if (handler->filter(handle, type, code, value))
  				filtered = true;
  		}
  	}
82ba56c27   Dmitry Torokhov   Input: use full R...
100
  	rcu_read_unlock();
8006479c9   Dmitry Torokhov   Input: implement ...
101
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102

8006479c9   Dmitry Torokhov   Input: implement ...
103
104
105
106
107
108
109
110
111
  /*
   * Generate software autorepeat event. Note that we take
   * dev->event_lock here to avoid racing with input_event
   * which may cause keys get "stuck".
   */
  static void input_repeat_key(unsigned long data)
  {
  	struct input_dev *dev = (void *) data;
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112

8006479c9   Dmitry Torokhov   Input: implement ...
113
  	spin_lock_irqsave(&dev->event_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114

8006479c9   Dmitry Torokhov   Input: implement ...
115
116
  	if (test_bit(dev->repeat_key, dev->key) &&
  	    is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117

9ae4345a4   Dmitry Torokhov   Revert "Input: do...
118
  		input_pass_event(dev, EV_KEY, dev->repeat_key, 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119

8006479c9   Dmitry Torokhov   Input: implement ...
120
121
122
123
124
125
126
  		if (dev->sync) {
  			/*
  			 * Only send SYN_REPORT if we are not in a middle
  			 * of driver parsing a new hardware packet.
  			 * Otherwise assume that the driver will send
  			 * SYN_REPORT once it's done.
  			 */
9ae4345a4   Dmitry Torokhov   Revert "Input: do...
127
  			input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
8006479c9   Dmitry Torokhov   Input: implement ...
128
  		}
315810668   Richard Purdie   [PATCH] Input: Ad...
129

8006479c9   Dmitry Torokhov   Input: implement ...
130
131
132
133
  		if (dev->rep[REP_PERIOD])
  			mod_timer(&dev->timer, jiffies +
  					msecs_to_jiffies(dev->rep[REP_PERIOD]));
  	}
315810668   Richard Purdie   [PATCH] Input: Ad...
134

8006479c9   Dmitry Torokhov   Input: implement ...
135
136
  	spin_unlock_irqrestore(&dev->event_lock, flags);
  }
315810668   Richard Purdie   [PATCH] Input: Ad...
137

8006479c9   Dmitry Torokhov   Input: implement ...
138
139
140
141
142
143
144
145
146
147
  static void input_start_autorepeat(struct input_dev *dev, int code)
  {
  	if (test_bit(EV_REP, dev->evbit) &&
  	    dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] &&
  	    dev->timer.data) {
  		dev->repeat_key = code;
  		mod_timer(&dev->timer,
  			  jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]));
  	}
  }
315810668   Richard Purdie   [PATCH] Input: Ad...
148

e7b5c1ef4   Johannes Berg   Input: stop autor...
149
150
151
152
  static void input_stop_autorepeat(struct input_dev *dev)
  {
  	del_timer(&dev->timer);
  }
8006479c9   Dmitry Torokhov   Input: implement ...
153
154
155
156
  #define INPUT_IGNORE_EVENT	0
  #define INPUT_PASS_TO_HANDLERS	1
  #define INPUT_PASS_TO_DEVICE	2
  #define INPUT_PASS_TO_ALL	(INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157

40d007e7d   Henrik Rydberg   Input: introduce ...
158
159
160
161
162
163
164
165
166
  static int input_handle_abs_event(struct input_dev *dev,
  				  unsigned int code, int *pval)
  {
  	bool is_mt_event;
  	int *pold;
  
  	if (code == ABS_MT_SLOT) {
  		/*
  		 * "Stage" the event; we'll flush it later, when we
144c0f883   Dmitry Torokhov   Input: fix a few ...
167
  		 * get actual touch data.
40d007e7d   Henrik Rydberg   Input: introduce ...
168
169
170
171
172
173
174
175
176
177
  		 */
  		if (*pval >= 0 && *pval < dev->mtsize)
  			dev->slot = *pval;
  
  		return INPUT_IGNORE_EVENT;
  	}
  
  	is_mt_event = code >= ABS_MT_FIRST && code <= ABS_MT_LAST;
  
  	if (!is_mt_event) {
d31b2865a   Daniel Mack   Input: dynamicall...
178
  		pold = &dev->absinfo[code].value;
40d007e7d   Henrik Rydberg   Input: introduce ...
179
180
181
182
183
  	} else if (dev->mt) {
  		struct input_mt_slot *mtslot = &dev->mt[dev->slot];
  		pold = &mtslot->abs[code - ABS_MT_FIRST];
  	} else {
  		/*
144c0f883   Dmitry Torokhov   Input: fix a few ...
184
  		 * Bypass filtering for multi-touch events when
40d007e7d   Henrik Rydberg   Input: introduce ...
185
186
187
188
189
190
191
  		 * not employing slots.
  		 */
  		pold = NULL;
  	}
  
  	if (pold) {
  		*pval = input_defuzz_abs_event(*pval, *pold,
d31b2865a   Daniel Mack   Input: dynamicall...
192
  						dev->absinfo[code].fuzz);
40d007e7d   Henrik Rydberg   Input: introduce ...
193
194
195
196
197
198
199
  		if (*pold == *pval)
  			return INPUT_IGNORE_EVENT;
  
  		*pold = *pval;
  	}
  
  	/* Flush pending "slot" event */
987a6c029   Daniel Mack   Input: switch to ...
200
201
  	if (is_mt_event && dev->slot != input_abs_get_val(dev, ABS_MT_SLOT)) {
  		input_abs_set_val(dev, ABS_MT_SLOT, dev->slot);
9ae4345a4   Dmitry Torokhov   Revert "Input: do...
202
  		input_pass_event(dev, EV_ABS, ABS_MT_SLOT, dev->slot);
40d007e7d   Henrik Rydberg   Input: introduce ...
203
204
205
206
  	}
  
  	return INPUT_PASS_TO_HANDLERS;
  }
8006479c9   Dmitry Torokhov   Input: implement ...
207
208
209
210
  static void input_handle_event(struct input_dev *dev,
  			       unsigned int type, unsigned int code, int value)
  {
  	int disposition = INPUT_IGNORE_EVENT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211

8006479c9   Dmitry Torokhov   Input: implement ...
212
  	switch (type) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213

8006479c9   Dmitry Torokhov   Input: implement ...
214
215
216
217
218
  	case EV_SYN:
  		switch (code) {
  		case SYN_CONFIG:
  			disposition = INPUT_PASS_TO_ALL;
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219

8006479c9   Dmitry Torokhov   Input: implement ...
220
221
  		case SYN_REPORT:
  			if (!dev->sync) {
20da92de8   Dmitry Torokhov   Input: change inp...
222
  				dev->sync = true;
8006479c9   Dmitry Torokhov   Input: implement ...
223
  				disposition = INPUT_PASS_TO_HANDLERS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
  			break;
5e5ee686e   Henrik Rydberg   Input: add detail...
226
  		case SYN_MT_REPORT:
20da92de8   Dmitry Torokhov   Input: change inp...
227
  			dev->sync = false;
5e5ee686e   Henrik Rydberg   Input: add detail...
228
229
  			disposition = INPUT_PASS_TO_HANDLERS;
  			break;
8006479c9   Dmitry Torokhov   Input: implement ...
230
231
  		}
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232

8006479c9   Dmitry Torokhov   Input: implement ...
233
234
235
  	case EV_KEY:
  		if (is_event_supported(code, dev->keybit, KEY_MAX) &&
  		    !!test_bit(code, dev->key) != value) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236

8006479c9   Dmitry Torokhov   Input: implement ...
237
238
239
240
  			if (value != 2) {
  				__change_bit(code, dev->key);
  				if (value)
  					input_start_autorepeat(dev, code);
e7b5c1ef4   Johannes Berg   Input: stop autor...
241
242
  				else
  					input_stop_autorepeat(dev);
8006479c9   Dmitry Torokhov   Input: implement ...
243
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
244

8006479c9   Dmitry Torokhov   Input: implement ...
245
246
247
  			disposition = INPUT_PASS_TO_HANDLERS;
  		}
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
248

8006479c9   Dmitry Torokhov   Input: implement ...
249
250
251
  	case EV_SW:
  		if (is_event_supported(code, dev->swbit, SW_MAX) &&
  		    !!test_bit(code, dev->sw) != value) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252

8006479c9   Dmitry Torokhov   Input: implement ...
253
254
255
256
  			__change_bit(code, dev->sw);
  			disposition = INPUT_PASS_TO_HANDLERS;
  		}
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257

8006479c9   Dmitry Torokhov   Input: implement ...
258
  	case EV_ABS:
40d007e7d   Henrik Rydberg   Input: introduce ...
259
  		if (is_event_supported(code, dev->absbit, ABS_MAX))
9ae4345a4   Dmitry Torokhov   Revert "Input: do...
260
  			disposition = input_handle_abs_event(dev, code, &value);
61994a61b   Henrik Rydberg   Input: allow cert...
261

8006479c9   Dmitry Torokhov   Input: implement ...
262
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263

8006479c9   Dmitry Torokhov   Input: implement ...
264
265
266
  	case EV_REL:
  		if (is_event_supported(code, dev->relbit, REL_MAX) && value)
  			disposition = INPUT_PASS_TO_HANDLERS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267

8006479c9   Dmitry Torokhov   Input: implement ...
268
  		break;
1e0afb288   Dmitry Torokhov   Input: fix format...
269

8006479c9   Dmitry Torokhov   Input: implement ...
270
271
272
  	case EV_MSC:
  		if (is_event_supported(code, dev->mscbit, MSC_MAX))
  			disposition = INPUT_PASS_TO_ALL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273

8006479c9   Dmitry Torokhov   Input: implement ...
274
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
275

8006479c9   Dmitry Torokhov   Input: implement ...
276
277
278
  	case EV_LED:
  		if (is_event_supported(code, dev->ledbit, LED_MAX) &&
  		    !!test_bit(code, dev->led) != value) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279

8006479c9   Dmitry Torokhov   Input: implement ...
280
281
282
283
284
285
286
  			__change_bit(code, dev->led);
  			disposition = INPUT_PASS_TO_ALL;
  		}
  		break;
  
  	case EV_SND:
  		if (is_event_supported(code, dev->sndbit, SND_MAX)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287

8fdc19486   Dmitry Torokhov   Input: make EVIOC...
288
  			if (!!test_bit(code, dev->snd) != !!value)
8006479c9   Dmitry Torokhov   Input: implement ...
289
290
291
292
  				__change_bit(code, dev->snd);
  			disposition = INPUT_PASS_TO_ALL;
  		}
  		break;
8fdc19486   Dmitry Torokhov   Input: make EVIOC...
293

8006479c9   Dmitry Torokhov   Input: implement ...
294
295
296
297
298
299
  	case EV_REP:
  		if (code <= REP_MAX && value >= 0 && dev->rep[code] != value) {
  			dev->rep[code] = value;
  			disposition = INPUT_PASS_TO_ALL;
  		}
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
300

8006479c9   Dmitry Torokhov   Input: implement ...
301
302
303
304
  	case EV_FF:
  		if (value >= 0)
  			disposition = INPUT_PASS_TO_ALL;
  		break;
ed2fa4dd4   Richard Purdie   Input: pass EV_PW...
305
306
307
308
  
  	case EV_PWR:
  		disposition = INPUT_PASS_TO_ALL;
  		break;
8006479c9   Dmitry Torokhov   Input: implement ...
309
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
310

c98122828   Dmitry Torokhov   Input: don't rese...
311
  	if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
20da92de8   Dmitry Torokhov   Input: change inp...
312
  		dev->sync = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
313

8006479c9   Dmitry Torokhov   Input: implement ...
314
315
  	if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)
  		dev->event(dev, type, code, value);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
316

8006479c9   Dmitry Torokhov   Input: implement ...
317
  	if (disposition & INPUT_PASS_TO_HANDLERS)
9ae4345a4   Dmitry Torokhov   Revert "Input: do...
318
  		input_pass_event(dev, type, code, value);
8006479c9   Dmitry Torokhov   Input: implement ...
319
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320

8006479c9   Dmitry Torokhov   Input: implement ...
321
322
323
324
325
326
327
328
  /**
   * input_event() - report new input event
   * @dev: device that generated the event
   * @type: type of the event
   * @code: event code
   * @value: value of the event
   *
   * This function should be used by drivers implementing various input
df2d4637b   Dmitry Torokhov   Input: document u...
329
330
331
332
333
334
335
336
   * devices to report input events. See also input_inject_event().
   *
   * NOTE: input_event() may be safely used right after input device was
   * allocated with input_allocate_device(), even before it is registered
   * with input_register_device(), but the event will not reach any of the
   * input handlers. Such early invocation of input_event() may be used
   * to 'seed' initial state of a switch or initial position of absolute
   * axis, etc.
8006479c9   Dmitry Torokhov   Input: implement ...
337
   */
8006479c9   Dmitry Torokhov   Input: implement ...
338
339
340
341
  void input_event(struct input_dev *dev,
  		 unsigned int type, unsigned int code, int value)
  {
  	unsigned long flags;
509ca1a93   Anssi Hannula   Input: implement ...
342

8006479c9   Dmitry Torokhov   Input: implement ...
343
  	if (is_event_supported(type, dev->evbit, EV_MAX)) {
509ca1a93   Anssi Hannula   Input: implement ...
344

8006479c9   Dmitry Torokhov   Input: implement ...
345
346
  		spin_lock_irqsave(&dev->event_lock, flags);
  		add_input_randomness(type, code, value);
9ae4345a4   Dmitry Torokhov   Revert "Input: do...
347
  		input_handle_event(dev, type, code, value);
8006479c9   Dmitry Torokhov   Input: implement ...
348
  		spin_unlock_irqrestore(&dev->event_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
349
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350
  }
ca56fe07f   Dmitry Torokhov   Input: rearrange ...
351
  EXPORT_SYMBOL(input_event);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
352

0e739d287   Dmitry Torokhov   Input: introduce ...
353
354
355
356
357
358
359
  /**
   * input_inject_event() - send input event from input handler
   * @handle: input handle to send event through
   * @type: type of the event
   * @code: event code
   * @value: value of the event
   *
8006479c9   Dmitry Torokhov   Input: implement ...
360
361
362
   * Similar to input_event() but will ignore event if device is
   * "grabbed" and handle injecting event is not the one that owns
   * the device.
0e739d287   Dmitry Torokhov   Input: introduce ...
363
   */
8006479c9   Dmitry Torokhov   Input: implement ...
364
365
  void input_inject_event(struct input_handle *handle,
  			unsigned int type, unsigned int code, int value)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366
  {
8006479c9   Dmitry Torokhov   Input: implement ...
367
368
369
  	struct input_dev *dev = handle->dev;
  	struct input_handle *grab;
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370

8006479c9   Dmitry Torokhov   Input: implement ...
371
372
  	if (is_event_supported(type, dev->evbit, EV_MAX)) {
  		spin_lock_irqsave(&dev->event_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
373

82ba56c27   Dmitry Torokhov   Input: use full R...
374
  		rcu_read_lock();
8006479c9   Dmitry Torokhov   Input: implement ...
375
376
  		grab = rcu_dereference(dev->grab);
  		if (!grab || grab == handle)
9ae4345a4   Dmitry Torokhov   Revert "Input: do...
377
  			input_handle_event(dev, type, code, value);
82ba56c27   Dmitry Torokhov   Input: use full R...
378
  		rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
379

8006479c9   Dmitry Torokhov   Input: implement ...
380
381
  		spin_unlock_irqrestore(&dev->event_lock, flags);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
382
  }
8006479c9   Dmitry Torokhov   Input: implement ...
383
  EXPORT_SYMBOL(input_inject_event);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
384

8006479c9   Dmitry Torokhov   Input: implement ...
385
  /**
d31b2865a   Daniel Mack   Input: dynamicall...
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
   * input_alloc_absinfo - allocates array of input_absinfo structs
   * @dev: the input device emitting absolute events
   *
   * If the absinfo struct the caller asked for is already allocated, this
   * functions will not do anything.
   */
  void input_alloc_absinfo(struct input_dev *dev)
  {
  	if (!dev->absinfo)
  		dev->absinfo = kcalloc(ABS_CNT, sizeof(struct input_absinfo),
  					GFP_KERNEL);
  
  	WARN(!dev->absinfo, "%s(): kcalloc() failed?
  ", __func__);
  }
  EXPORT_SYMBOL(input_alloc_absinfo);
  
  void input_set_abs_params(struct input_dev *dev, unsigned int axis,
  			  int min, int max, int fuzz, int flat)
  {
  	struct input_absinfo *absinfo;
  
  	input_alloc_absinfo(dev);
  	if (!dev->absinfo)
  		return;
  
  	absinfo = &dev->absinfo[axis];
  	absinfo->minimum = min;
  	absinfo->maximum = max;
  	absinfo->fuzz = fuzz;
  	absinfo->flat = flat;
  
  	dev->absbit[BIT_WORD(axis)] |= BIT_MASK(axis);
  }
  EXPORT_SYMBOL(input_set_abs_params);
  
  
  /**
8006479c9   Dmitry Torokhov   Input: implement ...
424
425
426
427
428
429
430
   * input_grab_device - grabs device for exclusive use
   * @handle: input handle that wants to own the device
   *
   * When a device is grabbed by an input handle all events generated by
   * the device are delivered only to this handle. Also events injected
   * by other input handles are ignored while device is grabbed.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431
432
  int input_grab_device(struct input_handle *handle)
  {
8006479c9   Dmitry Torokhov   Input: implement ...
433
434
  	struct input_dev *dev = handle->dev;
  	int retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435

8006479c9   Dmitry Torokhov   Input: implement ...
436
437
438
439
440
441
442
443
444
445
  	retval = mutex_lock_interruptible(&dev->mutex);
  	if (retval)
  		return retval;
  
  	if (dev->grab) {
  		retval = -EBUSY;
  		goto out;
  	}
  
  	rcu_assign_pointer(dev->grab, handle);
8006479c9   Dmitry Torokhov   Input: implement ...
446
447
448
449
  
   out:
  	mutex_unlock(&dev->mutex);
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
450
  }
ca56fe07f   Dmitry Torokhov   Input: rearrange ...
451
  EXPORT_SYMBOL(input_grab_device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
452

8006479c9   Dmitry Torokhov   Input: implement ...
453
  static void __input_release_device(struct input_handle *handle)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
454
  {
a2b2ed2ce   Andrew Morton   Input: fix list i...
455
  	struct input_dev *dev = handle->dev;
c7e8dc6ee   Dmitry Torokhov   Input: add start(...
456

a2b2ed2ce   Andrew Morton   Input: fix list i...
457
  	if (dev->grab == handle) {
8006479c9   Dmitry Torokhov   Input: implement ...
458
459
  		rcu_assign_pointer(dev->grab, NULL);
  		/* Make sure input_pass_event() notices that grab is gone */
82ba56c27   Dmitry Torokhov   Input: use full R...
460
  		synchronize_rcu();
a2b2ed2ce   Andrew Morton   Input: fix list i...
461
462
  
  		list_for_each_entry(handle, &dev->h_list, d_node)
8006479c9   Dmitry Torokhov   Input: implement ...
463
  			if (handle->open && handle->handler->start)
c7e8dc6ee   Dmitry Torokhov   Input: add start(...
464
465
  				handle->handler->start(handle);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
466
  }
8006479c9   Dmitry Torokhov   Input: implement ...
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
  
  /**
   * input_release_device - release previously grabbed device
   * @handle: input handle that owns the device
   *
   * Releases previously grabbed device so that other input handles can
   * start receiving input events. Upon release all handlers attached
   * to the device have their start() method called so they have a change
   * to synchronize device state with the rest of the system.
   */
  void input_release_device(struct input_handle *handle)
  {
  	struct input_dev *dev = handle->dev;
  
  	mutex_lock(&dev->mutex);
  	__input_release_device(handle);
  	mutex_unlock(&dev->mutex);
  }
ca56fe07f   Dmitry Torokhov   Input: rearrange ...
485
  EXPORT_SYMBOL(input_release_device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
486

8006479c9   Dmitry Torokhov   Input: implement ...
487
488
489
490
491
492
493
  /**
   * input_open_device - open input device
   * @handle: handle through which device is being accessed
   *
   * This function should be called by input handlers when they
   * want to start receive events from given input device.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
494
495
  int input_open_device(struct input_handle *handle)
  {
0fbf87caf   Dmitry Torokhov   Input: add semaph...
496
  	struct input_dev *dev = handle->dev;
8006479c9   Dmitry Torokhov   Input: implement ...
497
  	int retval;
0fbf87caf   Dmitry Torokhov   Input: add semaph...
498

8006479c9   Dmitry Torokhov   Input: implement ...
499
500
501
502
503
504
505
506
  	retval = mutex_lock_interruptible(&dev->mutex);
  	if (retval)
  		return retval;
  
  	if (dev->going_away) {
  		retval = -ENODEV;
  		goto out;
  	}
0fbf87caf   Dmitry Torokhov   Input: add semaph...
507

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
508
  	handle->open++;
0fbf87caf   Dmitry Torokhov   Input: add semaph...
509
510
  
  	if (!dev->users++ && dev->open)
8006479c9   Dmitry Torokhov   Input: implement ...
511
512
513
514
515
516
517
518
519
  		retval = dev->open(dev);
  
  	if (retval) {
  		dev->users--;
  		if (!--handle->open) {
  			/*
  			 * Make sure we are not delivering any more events
  			 * through this handle
  			 */
82ba56c27   Dmitry Torokhov   Input: use full R...
520
  			synchronize_rcu();
8006479c9   Dmitry Torokhov   Input: implement ...
521
522
  		}
  	}
0fbf87caf   Dmitry Torokhov   Input: add semaph...
523

8006479c9   Dmitry Torokhov   Input: implement ...
524
   out:
e676c232e   Jes Sorensen   Input: input core...
525
  	mutex_unlock(&dev->mutex);
8006479c9   Dmitry Torokhov   Input: implement ...
526
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
527
  }
ca56fe07f   Dmitry Torokhov   Input: rearrange ...
528
  EXPORT_SYMBOL(input_open_device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
529

8006479c9   Dmitry Torokhov   Input: implement ...
530
  int input_flush_device(struct input_handle *handle, struct file *file)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
531
  {
8006479c9   Dmitry Torokhov   Input: implement ...
532
533
  	struct input_dev *dev = handle->dev;
  	int retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
534

8006479c9   Dmitry Torokhov   Input: implement ...
535
536
537
538
539
540
541
542
543
  	retval = mutex_lock_interruptible(&dev->mutex);
  	if (retval)
  		return retval;
  
  	if (dev->flush)
  		retval = dev->flush(dev, file);
  
  	mutex_unlock(&dev->mutex);
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
544
  }
ca56fe07f   Dmitry Torokhov   Input: rearrange ...
545
  EXPORT_SYMBOL(input_flush_device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
546

8006479c9   Dmitry Torokhov   Input: implement ...
547
548
549
550
551
552
553
  /**
   * input_close_device - close input device
   * @handle: handle through which device is being accessed
   *
   * This function should be called by input handlers when they
   * want to stop receive events from given input device.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
554
555
  void input_close_device(struct input_handle *handle)
  {
0fbf87caf   Dmitry Torokhov   Input: add semaph...
556
  	struct input_dev *dev = handle->dev;
e676c232e   Jes Sorensen   Input: input core...
557
  	mutex_lock(&dev->mutex);
0fbf87caf   Dmitry Torokhov   Input: add semaph...
558

8006479c9   Dmitry Torokhov   Input: implement ...
559
  	__input_release_device(handle);
0fbf87caf   Dmitry Torokhov   Input: add semaph...
560
561
  	if (!--dev->users && dev->close)
  		dev->close(dev);
8006479c9   Dmitry Torokhov   Input: implement ...
562
563
564
  
  	if (!--handle->open) {
  		/*
82ba56c27   Dmitry Torokhov   Input: use full R...
565
  		 * synchronize_rcu() makes sure that input_pass_event()
8006479c9   Dmitry Torokhov   Input: implement ...
566
567
568
  		 * completed and that no more input events are delivered
  		 * through this handle
  		 */
82ba56c27   Dmitry Torokhov   Input: use full R...
569
  		synchronize_rcu();
8006479c9   Dmitry Torokhov   Input: implement ...
570
  	}
0fbf87caf   Dmitry Torokhov   Input: add semaph...
571

e676c232e   Jes Sorensen   Input: input core...
572
  	mutex_unlock(&dev->mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
573
  }
ca56fe07f   Dmitry Torokhov   Input: rearrange ...
574
  EXPORT_SYMBOL(input_close_device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
575

8006479c9   Dmitry Torokhov   Input: implement ...
576
  /*
866d7d7b4   Oliver Neukum   Input: release pr...
577
578
579
580
581
582
583
584
585
586
587
   * Simulate keyup events for all keys that are marked as pressed.
   * The function must be called with dev->event_lock held.
   */
  static void input_dev_release_keys(struct input_dev *dev)
  {
  	int code;
  
  	if (is_event_supported(EV_KEY, dev->evbit, EV_MAX)) {
  		for (code = 0; code <= KEY_MAX; code++) {
  			if (is_event_supported(code, dev->keybit, KEY_MAX) &&
  			    __test_and_clear_bit(code, dev->key)) {
9ae4345a4   Dmitry Torokhov   Revert "Input: do...
588
  				input_pass_event(dev, EV_KEY, code, 0);
866d7d7b4   Oliver Neukum   Input: release pr...
589
590
  			}
  		}
9ae4345a4   Dmitry Torokhov   Revert "Input: do...
591
  		input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
866d7d7b4   Oliver Neukum   Input: release pr...
592
593
594
595
  	}
  }
  
  /*
8006479c9   Dmitry Torokhov   Input: implement ...
596
597
598
599
600
   * Prepare device for unregistering
   */
  static void input_disconnect_device(struct input_dev *dev)
  {
  	struct input_handle *handle;
8006479c9   Dmitry Torokhov   Input: implement ...
601
602
603
604
605
606
607
  
  	/*
  	 * Mark device as going away. Note that we take dev->mutex here
  	 * not to protect access to dev->going_away but rather to ensure
  	 * that there are no threads in the middle of input_open_device()
  	 */
  	mutex_lock(&dev->mutex);
ffd0db971   Dmitry Torokhov   Input: add generi...
608
  	dev->going_away = true;
8006479c9   Dmitry Torokhov   Input: implement ...
609
610
611
612
613
614
615
616
617
618
  	mutex_unlock(&dev->mutex);
  
  	spin_lock_irq(&dev->event_lock);
  
  	/*
  	 * Simulate keyup events for all pressed keys so that handlers
  	 * are not left with "stuck" keys. The driver may continue
  	 * generate events even after we done here but they will not
  	 * reach any handlers.
  	 */
866d7d7b4   Oliver Neukum   Input: release pr...
619
  	input_dev_release_keys(dev);
8006479c9   Dmitry Torokhov   Input: implement ...
620
621
622
623
624
625
  
  	list_for_each_entry(handle, &dev->h_list, d_node)
  		handle->open = 0;
  
  	spin_unlock_irq(&dev->event_lock);
  }
8613e4c28   Mauro Carvalho Chehab   Input: add suppor...
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
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
  /**
   * input_scancode_to_scalar() - converts scancode in &struct input_keymap_entry
   * @ke: keymap entry containing scancode to be converted.
   * @scancode: pointer to the location where converted scancode should
   *	be stored.
   *
   * This function is used to convert scancode stored in &struct keymap_entry
   * into scalar form understood by legacy keymap handling methods. These
   * methods expect scancodes to be represented as 'unsigned int'.
   */
  int input_scancode_to_scalar(const struct input_keymap_entry *ke,
  			     unsigned int *scancode)
  {
  	switch (ke->len) {
  	case 1:
  		*scancode = *((u8 *)ke->scancode);
  		break;
  
  	case 2:
  		*scancode = *((u16 *)ke->scancode);
  		break;
  
  	case 4:
  		*scancode = *((u32 *)ke->scancode);
  		break;
  
  	default:
  		return -EINVAL;
  	}
  
  	return 0;
  }
  EXPORT_SYMBOL(input_scancode_to_scalar);
  
  /*
   * Those routines handle the default case where no [gs]etkeycode() is
   * defined. In this case, an array indexed by the scancode is used.
   */
  
  static unsigned int input_fetch_keycode(struct input_dev *dev,
  					unsigned int index)
c8e4c7727   Marvin Raaijmakers   Input: add getkey...
667
668
  {
  	switch (dev->keycodesize) {
8613e4c28   Mauro Carvalho Chehab   Input: add suppor...
669
670
  	case 1:
  		return ((u8 *)dev->keycode)[index];
c8e4c7727   Marvin Raaijmakers   Input: add getkey...
671

8613e4c28   Mauro Carvalho Chehab   Input: add suppor...
672
673
  	case 2:
  		return ((u16 *)dev->keycode)[index];
c8e4c7727   Marvin Raaijmakers   Input: add getkey...
674

8613e4c28   Mauro Carvalho Chehab   Input: add suppor...
675
676
  	default:
  		return ((u32 *)dev->keycode)[index];
c8e4c7727   Marvin Raaijmakers   Input: add getkey...
677
678
679
680
  	}
  }
  
  static int input_default_getkeycode(struct input_dev *dev,
8613e4c28   Mauro Carvalho Chehab   Input: add suppor...
681
  				    struct input_keymap_entry *ke)
c8e4c7727   Marvin Raaijmakers   Input: add getkey...
682
  {
8613e4c28   Mauro Carvalho Chehab   Input: add suppor...
683
684
  	unsigned int index;
  	int error;
c8e4c7727   Marvin Raaijmakers   Input: add getkey...
685
686
  	if (!dev->keycodesize)
  		return -EINVAL;
8613e4c28   Mauro Carvalho Chehab   Input: add suppor...
687
688
689
690
691
692
693
694
695
  	if (ke->flags & INPUT_KEYMAP_BY_INDEX)
  		index = ke->index;
  	else {
  		error = input_scancode_to_scalar(ke, &index);
  		if (error)
  			return error;
  	}
  
  	if (index >= dev->keycodemax)
c8e4c7727   Marvin Raaijmakers   Input: add getkey...
696
  		return -EINVAL;
8613e4c28   Mauro Carvalho Chehab   Input: add suppor...
697
698
699
700
  	ke->keycode = input_fetch_keycode(dev, index);
  	ke->index = index;
  	ke->len = sizeof(index);
  	memcpy(ke->scancode, &index, sizeof(index));
c8e4c7727   Marvin Raaijmakers   Input: add getkey...
701
702
703
704
705
  
  	return 0;
  }
  
  static int input_default_setkeycode(struct input_dev *dev,
8613e4c28   Mauro Carvalho Chehab   Input: add suppor...
706
707
  				    const struct input_keymap_entry *ke,
  				    unsigned int *old_keycode)
c8e4c7727   Marvin Raaijmakers   Input: add getkey...
708
  {
8613e4c28   Mauro Carvalho Chehab   Input: add suppor...
709
710
  	unsigned int index;
  	int error;
c8e4c7727   Marvin Raaijmakers   Input: add getkey...
711
  	int i;
8613e4c28   Mauro Carvalho Chehab   Input: add suppor...
712
  	if (!dev->keycodesize)
c8e4c7727   Marvin Raaijmakers   Input: add getkey...
713
  		return -EINVAL;
8613e4c28   Mauro Carvalho Chehab   Input: add suppor...
714
715
716
717
718
719
720
721
722
  	if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
  		index = ke->index;
  	} else {
  		error = input_scancode_to_scalar(ke, &index);
  		if (error)
  			return error;
  	}
  
  	if (index >= dev->keycodemax)
c8e4c7727   Marvin Raaijmakers   Input: add getkey...
723
  		return -EINVAL;
de391d125   Mattia Dongili   Input: fix typo i...
724
  	if (dev->keycodesize < sizeof(ke->keycode) &&
8613e4c28   Mauro Carvalho Chehab   Input: add suppor...
725
  			(ke->keycode >> (dev->keycodesize * 8)))
c8e4c7727   Marvin Raaijmakers   Input: add getkey...
726
727
728
729
730
  		return -EINVAL;
  
  	switch (dev->keycodesize) {
  		case 1: {
  			u8 *k = (u8 *)dev->keycode;
8613e4c28   Mauro Carvalho Chehab   Input: add suppor...
731
732
  			*old_keycode = k[index];
  			k[index] = ke->keycode;
c8e4c7727   Marvin Raaijmakers   Input: add getkey...
733
734
735
736
  			break;
  		}
  		case 2: {
  			u16 *k = (u16 *)dev->keycode;
8613e4c28   Mauro Carvalho Chehab   Input: add suppor...
737
738
  			*old_keycode = k[index];
  			k[index] = ke->keycode;
c8e4c7727   Marvin Raaijmakers   Input: add getkey...
739
740
741
742
  			break;
  		}
  		default: {
  			u32 *k = (u32 *)dev->keycode;
8613e4c28   Mauro Carvalho Chehab   Input: add suppor...
743
744
  			*old_keycode = k[index];
  			k[index] = ke->keycode;
c8e4c7727   Marvin Raaijmakers   Input: add getkey...
745
746
747
  			break;
  		}
  	}
8613e4c28   Mauro Carvalho Chehab   Input: add suppor...
748
749
  	__clear_bit(*old_keycode, dev->keybit);
  	__set_bit(ke->keycode, dev->keybit);
c8e4c7727   Marvin Raaijmakers   Input: add getkey...
750
751
  
  	for (i = 0; i < dev->keycodemax; i++) {
8613e4c28   Mauro Carvalho Chehab   Input: add suppor...
752
753
  		if (input_fetch_keycode(dev, i) == *old_keycode) {
  			__set_bit(*old_keycode, dev->keybit);
c8e4c7727   Marvin Raaijmakers   Input: add getkey...
754
755
756
757
758
759
  			break; /* Setting the bit twice is useless, so break */
  		}
  	}
  
  	return 0;
  }
f4f37c8ec   Dmitry Torokhov   Input: Add proper...
760
761
762
  /**
   * input_get_keycode - retrieve keycode currently mapped to a given scancode
   * @dev: input device which keymap is being queried
8613e4c28   Mauro Carvalho Chehab   Input: add suppor...
763
   * @ke: keymap entry
f4f37c8ec   Dmitry Torokhov   Input: Add proper...
764
765
   *
   * This function should be called by anyone interested in retrieving current
8613e4c28   Mauro Carvalho Chehab   Input: add suppor...
766
   * keymap. Presently evdev handlers use it.
f4f37c8ec   Dmitry Torokhov   Input: Add proper...
767
   */
8613e4c28   Mauro Carvalho Chehab   Input: add suppor...
768
  int input_get_keycode(struct input_dev *dev, struct input_keymap_entry *ke)
f4f37c8ec   Dmitry Torokhov   Input: Add proper...
769
  {
2e2e3b96d   Dmitry Torokhov   Input: sparse-key...
770
771
772
773
  	unsigned long flags;
  	int retval;
  
  	spin_lock_irqsave(&dev->event_lock, flags);
aebd636bd   Dmitry Torokhov   Input: switch com...
774
  	retval = dev->getkeycode(dev, ke);
8613e4c28   Mauro Carvalho Chehab   Input: add suppor...
775
  	spin_unlock_irqrestore(&dev->event_lock, flags);
aebd636bd   Dmitry Torokhov   Input: switch com...
776

2e2e3b96d   Dmitry Torokhov   Input: sparse-key...
777
  	return retval;
f4f37c8ec   Dmitry Torokhov   Input: Add proper...
778
779
780
781
  }
  EXPORT_SYMBOL(input_get_keycode);
  
  /**
8613e4c28   Mauro Carvalho Chehab   Input: add suppor...
782
   * input_set_keycode - attribute a keycode to a given scancode
f4f37c8ec   Dmitry Torokhov   Input: Add proper...
783
   * @dev: input device which keymap is being updated
8613e4c28   Mauro Carvalho Chehab   Input: add suppor...
784
   * @ke: new keymap entry
f4f37c8ec   Dmitry Torokhov   Input: Add proper...
785
786
787
788
   *
   * This function should be called by anyone needing to update current
   * keymap. Presently keyboard and evdev handlers use it.
   */
58b939959   Dmitry Torokhov   Input: scancode i...
789
  int input_set_keycode(struct input_dev *dev,
8613e4c28   Mauro Carvalho Chehab   Input: add suppor...
790
  		      const struct input_keymap_entry *ke)
f4f37c8ec   Dmitry Torokhov   Input: Add proper...
791
792
  {
  	unsigned long flags;
fd6cf3ddd   Dmitry Torokhov   Input: fix signed...
793
  	unsigned int old_keycode;
f4f37c8ec   Dmitry Torokhov   Input: Add proper...
794
  	int retval;
8613e4c28   Mauro Carvalho Chehab   Input: add suppor...
795
  	if (ke->keycode > KEY_MAX)
f4f37c8ec   Dmitry Torokhov   Input: Add proper...
796
797
798
  		return -EINVAL;
  
  	spin_lock_irqsave(&dev->event_lock, flags);
aebd636bd   Dmitry Torokhov   Input: switch com...
799
  	retval = dev->setkeycode(dev, ke, &old_keycode);
f4f37c8ec   Dmitry Torokhov   Input: Add proper...
800
801
  	if (retval)
  		goto out;
4f93df408   Dmitry Torokhov   Input: automatica...
802
803
  	/* Make sure KEY_RESERVED did not get enabled. */
  	__clear_bit(KEY_RESERVED, dev->keybit);
f4f37c8ec   Dmitry Torokhov   Input: Add proper...
804
805
806
807
808
809
810
  	/*
  	 * Simulate keyup event if keycode is not present
  	 * in the keymap anymore
  	 */
  	if (test_bit(EV_KEY, dev->evbit) &&
  	    !is_event_supported(old_keycode, dev->keybit, KEY_MAX) &&
  	    __test_and_clear_bit(old_keycode, dev->key)) {
9ae4345a4   Dmitry Torokhov   Revert "Input: do...
811
  		input_pass_event(dev, EV_KEY, old_keycode, 0);
f4f37c8ec   Dmitry Torokhov   Input: Add proper...
812
  		if (dev->sync)
9ae4345a4   Dmitry Torokhov   Revert "Input: do...
813
  			input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
f4f37c8ec   Dmitry Torokhov   Input: Add proper...
814
815
816
817
818
819
820
821
  	}
  
   out:
  	spin_unlock_irqrestore(&dev->event_lock, flags);
  
  	return retval;
  }
  EXPORT_SYMBOL(input_set_keycode);
c8e4c7727   Marvin Raaijmakers   Input: add getkey...
822

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
823
  #define MATCH_BIT(bit, max) \
7b19ada2e   Jiri Slaby   get rid of input ...
824
  		for (i = 0; i < BITS_TO_LONGS(max); i++) \
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
825
826
  			if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \
  				break; \
7b19ada2e   Jiri Slaby   get rid of input ...
827
  		if (i != BITS_TO_LONGS(max)) \
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
828
  			continue;
0b7024ac4   Dmitry Torokhov   Input: add match(...
829
  static const struct input_device_id *input_match_device(struct input_handler *handler,
66e661188   Dmitry Torokhov   Input: constify i...
830
  							struct input_dev *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
831
  {
0b7024ac4   Dmitry Torokhov   Input: add match(...
832
  	const struct input_device_id *id;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
833
  	int i;
0b7024ac4   Dmitry Torokhov   Input: add match(...
834
  	for (id = handler->id_table; id->flags || id->driver_info; id++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
835
836
  
  		if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)
ddc5d3414   Dmitry Torokhov   Input: move input...
837
  			if (id->bustype != dev->id.bustype)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
838
839
840
  				continue;
  
  		if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR)
ddc5d3414   Dmitry Torokhov   Input: move input...
841
  			if (id->vendor != dev->id.vendor)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
842
843
844
  				continue;
  
  		if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT)
ddc5d3414   Dmitry Torokhov   Input: move input...
845
  			if (id->product != dev->id.product)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
846
847
848
  				continue;
  
  		if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION)
ddc5d3414   Dmitry Torokhov   Input: move input...
849
  			if (id->version != dev->id.version)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
850
851
852
853
854
855
856
857
858
859
  				continue;
  
  		MATCH_BIT(evbit,  EV_MAX);
  		MATCH_BIT(keybit, KEY_MAX);
  		MATCH_BIT(relbit, REL_MAX);
  		MATCH_BIT(absbit, ABS_MAX);
  		MATCH_BIT(mscbit, MSC_MAX);
  		MATCH_BIT(ledbit, LED_MAX);
  		MATCH_BIT(sndbit, SND_MAX);
  		MATCH_BIT(ffbit,  FF_MAX);
ff13f98b9   Dmitry Torokhov   [PATCH] Input: ch...
860
  		MATCH_BIT(swbit,  SW_MAX);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
861

0b7024ac4   Dmitry Torokhov   Input: add match(...
862
863
  		if (!handler->match || handler->match(handler, dev))
  			return id;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
864
865
866
867
  	}
  
  	return NULL;
  }
5b2a08262   Dmitry Torokhov   Input: rework han...
868
869
870
871
  static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)
  {
  	const struct input_device_id *id;
  	int error;
0b7024ac4   Dmitry Torokhov   Input: add match(...
872
  	id = input_match_device(handler, dev);
5b2a08262   Dmitry Torokhov   Input: rework han...
873
874
875
876
877
  	if (!id)
  		return -ENODEV;
  
  	error = handler->connect(handler, dev, id);
  	if (error && error != -ENODEV)
da0c49011   Joe Perches   Input: use pr_fmt...
878
879
880
  		pr_err("failed to attach handler %s to device %s, error: %d
  ",
  		       handler->name, kobject_name(&dev->dev.kobj), error);
5b2a08262   Dmitry Torokhov   Input: rework han...
881
882
883
  
  	return error;
  }
15e184afa   Dmitry Torokhov   Input: add compat...
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
  #ifdef CONFIG_COMPAT
  
  static int input_bits_to_string(char *buf, int buf_size,
  				unsigned long bits, bool skip_empty)
  {
  	int len = 0;
  
  	if (INPUT_COMPAT_TEST) {
  		u32 dword = bits >> 32;
  		if (dword || !skip_empty)
  			len += snprintf(buf, buf_size, "%x ", dword);
  
  		dword = bits & 0xffffffffUL;
  		if (dword || !skip_empty || len)
  			len += snprintf(buf + len, max(buf_size - len, 0),
  					"%x", dword);
  	} else {
  		if (bits || !skip_empty)
  			len += snprintf(buf, buf_size, "%lx", bits);
  	}
  
  	return len;
  }
  
  #else /* !CONFIG_COMPAT */
  
  static int input_bits_to_string(char *buf, int buf_size,
  				unsigned long bits, bool skip_empty)
  {
  	return bits || !skip_empty ?
  		snprintf(buf, buf_size, "%lx", bits) : 0;
  }
  
  #endif
5b2a08262   Dmitry Torokhov   Input: rework han...
918

f96b434d3   Dmitry Torokhov   Input: rearrange ...
919
920
921
922
923
924
925
926
927
928
929
  #ifdef CONFIG_PROC_FS
  
  static struct proc_dir_entry *proc_bus_input_dir;
  static DECLARE_WAIT_QUEUE_HEAD(input_devices_poll_wait);
  static int input_devices_state;
  
  static inline void input_wakeup_procfs_readers(void)
  {
  	input_devices_state++;
  	wake_up(&input_devices_poll_wait);
  }
969b21cde   Dmitry Torokhov   Input: convert /p...
930
  static unsigned int input_proc_devices_poll(struct file *file, poll_table *wait)
f96b434d3   Dmitry Torokhov   Input: rearrange ...
931
  {
f96b434d3   Dmitry Torokhov   Input: rearrange ...
932
  	poll_wait(file, &input_devices_poll_wait, wait);
fa8866122   Dmitry Torokhov   Input: fix pollin...
933
934
  	if (file->f_version != input_devices_state) {
  		file->f_version = input_devices_state;
f96b434d3   Dmitry Torokhov   Input: rearrange ...
935
  		return POLLIN | POLLRDNORM;
fa8866122   Dmitry Torokhov   Input: fix pollin...
936
  	}
1e0afb288   Dmitry Torokhov   Input: fix format...
937

f96b434d3   Dmitry Torokhov   Input: rearrange ...
938
939
  	return 0;
  }
1572ca2a8   Dmitry Torokhov   Input: fix lockin...
940
941
942
943
944
945
946
  union input_seq_state {
  	struct {
  		unsigned short pos;
  		bool mutex_acquired;
  	};
  	void *p;
  };
969b21cde   Dmitry Torokhov   Input: convert /p...
947
948
  static void *input_devices_seq_start(struct seq_file *seq, loff_t *pos)
  {
1572ca2a8   Dmitry Torokhov   Input: fix lockin...
949
950
951
952
953
954
955
956
957
958
959
960
961
  	union input_seq_state *state = (union input_seq_state *)&seq->private;
  	int error;
  
  	/* We need to fit into seq->private pointer */
  	BUILD_BUG_ON(sizeof(union input_seq_state) != sizeof(seq->private));
  
  	error = mutex_lock_interruptible(&input_mutex);
  	if (error) {
  		state->mutex_acquired = false;
  		return ERR_PTR(error);
  	}
  
  	state->mutex_acquired = true;
f96b434d3   Dmitry Torokhov   Input: rearrange ...
962

ad5d972cd   Pavel Emelianov   Input: switch to ...
963
  	return seq_list_start(&input_dev_list, *pos);
969b21cde   Dmitry Torokhov   Input: convert /p...
964
  }
051b2feaa   Dmitry Torokhov   [PATCH] Input: sh...
965

969b21cde   Dmitry Torokhov   Input: convert /p...
966
967
  static void *input_devices_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  {
ad5d972cd   Pavel Emelianov   Input: switch to ...
968
  	return seq_list_next(v, &input_dev_list, pos);
969b21cde   Dmitry Torokhov   Input: convert /p...
969
  }
f96b434d3   Dmitry Torokhov   Input: rearrange ...
970

1572ca2a8   Dmitry Torokhov   Input: fix lockin...
971
  static void input_seq_stop(struct seq_file *seq, void *v)
969b21cde   Dmitry Torokhov   Input: convert /p...
972
  {
1572ca2a8   Dmitry Torokhov   Input: fix lockin...
973
974
975
976
  	union input_seq_state *state = (union input_seq_state *)&seq->private;
  
  	if (state->mutex_acquired)
  		mutex_unlock(&input_mutex);
969b21cde   Dmitry Torokhov   Input: convert /p...
977
  }
f96b434d3   Dmitry Torokhov   Input: rearrange ...
978

969b21cde   Dmitry Torokhov   Input: convert /p...
979
980
981
982
  static void input_seq_print_bitmap(struct seq_file *seq, const char *name,
  				   unsigned long *bitmap, int max)
  {
  	int i;
15e184afa   Dmitry Torokhov   Input: add compat...
983
984
  	bool skip_empty = true;
  	char buf[18];
f96b434d3   Dmitry Torokhov   Input: rearrange ...
985

969b21cde   Dmitry Torokhov   Input: convert /p...
986
  	seq_printf(seq, "B: %s=", name);
15e184afa   Dmitry Torokhov   Input: add compat...
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
  
  	for (i = BITS_TO_LONGS(max) - 1; i >= 0; i--) {
  		if (input_bits_to_string(buf, sizeof(buf),
  					 bitmap[i], skip_empty)) {
  			skip_empty = false;
  			seq_printf(seq, "%s%s", buf, i > 0 ? " " : "");
  		}
  	}
  
  	/*
  	 * If no output was produced print a single 0.
  	 */
  	if (skip_empty)
  		seq_puts(seq, "0");
969b21cde   Dmitry Torokhov   Input: convert /p...
1001
1002
1003
  	seq_putc(seq, '
  ');
  }
f96b434d3   Dmitry Torokhov   Input: rearrange ...
1004

969b21cde   Dmitry Torokhov   Input: convert /p...
1005
1006
1007
  static int input_devices_seq_show(struct seq_file *seq, void *v)
  {
  	struct input_dev *dev = container_of(v, struct input_dev, node);
9657d75c5   Dmitry Torokhov   Input: convert fr...
1008
  	const char *path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
969b21cde   Dmitry Torokhov   Input: convert /p...
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
  	struct input_handle *handle;
  
  	seq_printf(seq, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x
  ",
  		   dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version);
  
  	seq_printf(seq, "N: Name=\"%s\"
  ", dev->name ? dev->name : "");
  	seq_printf(seq, "P: Phys=%s
  ", dev->phys ? dev->phys : "");
  	seq_printf(seq, "S: Sysfs=%s
  ", path ? path : "");
15e03ae81   Dmitry Torokhov   Input: export 'un...
1021
1022
  	seq_printf(seq, "U: Uniq=%s
  ", dev->uniq ? dev->uniq : "");
969b21cde   Dmitry Torokhov   Input: convert /p...
1023
1024
1025
1026
1027
1028
  	seq_printf(seq, "H: Handlers=");
  
  	list_for_each_entry(handle, &dev->h_list, d_node)
  		seq_printf(seq, "%s ", handle->name);
  	seq_putc(seq, '
  ');
85b772003   Henrik Rydberg   Input: introduce ...
1029
  	input_seq_print_bitmap(seq, "PROP", dev->propbit, INPUT_PROP_MAX);
969b21cde   Dmitry Torokhov   Input: convert /p...
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
  	input_seq_print_bitmap(seq, "EV", dev->evbit, EV_MAX);
  	if (test_bit(EV_KEY, dev->evbit))
  		input_seq_print_bitmap(seq, "KEY", dev->keybit, KEY_MAX);
  	if (test_bit(EV_REL, dev->evbit))
  		input_seq_print_bitmap(seq, "REL", dev->relbit, REL_MAX);
  	if (test_bit(EV_ABS, dev->evbit))
  		input_seq_print_bitmap(seq, "ABS", dev->absbit, ABS_MAX);
  	if (test_bit(EV_MSC, dev->evbit))
  		input_seq_print_bitmap(seq, "MSC", dev->mscbit, MSC_MAX);
  	if (test_bit(EV_LED, dev->evbit))
  		input_seq_print_bitmap(seq, "LED", dev->ledbit, LED_MAX);
  	if (test_bit(EV_SND, dev->evbit))
  		input_seq_print_bitmap(seq, "SND", dev->sndbit, SND_MAX);
  	if (test_bit(EV_FF, dev->evbit))
  		input_seq_print_bitmap(seq, "FF", dev->ffbit, FF_MAX);
  	if (test_bit(EV_SW, dev->evbit))
  		input_seq_print_bitmap(seq, "SW", dev->swbit, SW_MAX);
  
  	seq_putc(seq, '
  ');
  
  	kfree(path);
  	return 0;
f96b434d3   Dmitry Torokhov   Input: rearrange ...
1053
  }
cec69c376   Jan Engelhardt   Input: constify f...
1054
  static const struct seq_operations input_devices_seq_ops = {
969b21cde   Dmitry Torokhov   Input: convert /p...
1055
1056
  	.start	= input_devices_seq_start,
  	.next	= input_devices_seq_next,
1572ca2a8   Dmitry Torokhov   Input: fix lockin...
1057
  	.stop	= input_seq_stop,
969b21cde   Dmitry Torokhov   Input: convert /p...
1058
1059
1060
1061
  	.show	= input_devices_seq_show,
  };
  
  static int input_proc_devices_open(struct inode *inode, struct file *file)
f96b434d3   Dmitry Torokhov   Input: rearrange ...
1062
  {
969b21cde   Dmitry Torokhov   Input: convert /p...
1063
1064
  	return seq_open(file, &input_devices_seq_ops);
  }
2b8693c06   Arjan van de Ven   [PATCH] mark stru...
1065
  static const struct file_operations input_devices_fileops = {
969b21cde   Dmitry Torokhov   Input: convert /p...
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
  	.owner		= THIS_MODULE,
  	.open		= input_proc_devices_open,
  	.poll		= input_proc_devices_poll,
  	.read		= seq_read,
  	.llseek		= seq_lseek,
  	.release	= seq_release,
  };
  
  static void *input_handlers_seq_start(struct seq_file *seq, loff_t *pos)
  {
1572ca2a8   Dmitry Torokhov   Input: fix lockin...
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
  	union input_seq_state *state = (union input_seq_state *)&seq->private;
  	int error;
  
  	/* We need to fit into seq->private pointer */
  	BUILD_BUG_ON(sizeof(union input_seq_state) != sizeof(seq->private));
  
  	error = mutex_lock_interruptible(&input_mutex);
  	if (error) {
  		state->mutex_acquired = false;
  		return ERR_PTR(error);
  	}
  
  	state->mutex_acquired = true;
  	state->pos = *pos;
8006479c9   Dmitry Torokhov   Input: implement ...
1090

ad5d972cd   Pavel Emelianov   Input: switch to ...
1091
  	return seq_list_start(&input_handler_list, *pos);
969b21cde   Dmitry Torokhov   Input: convert /p...
1092
  }
f96b434d3   Dmitry Torokhov   Input: rearrange ...
1093

969b21cde   Dmitry Torokhov   Input: convert /p...
1094
1095
  static void *input_handlers_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  {
1572ca2a8   Dmitry Torokhov   Input: fix lockin...
1096
  	union input_seq_state *state = (union input_seq_state *)&seq->private;
f96b434d3   Dmitry Torokhov   Input: rearrange ...
1097

1572ca2a8   Dmitry Torokhov   Input: fix lockin...
1098
1099
  	state->pos = *pos + 1;
  	return seq_list_next(v, &input_handler_list, pos);
969b21cde   Dmitry Torokhov   Input: convert /p...
1100
1101
1102
1103
1104
  }
  
  static int input_handlers_seq_show(struct seq_file *seq, void *v)
  {
  	struct input_handler *handler = container_of(v, struct input_handler, node);
1572ca2a8   Dmitry Torokhov   Input: fix lockin...
1105
  	union input_seq_state *state = (union input_seq_state *)&seq->private;
969b21cde   Dmitry Torokhov   Input: convert /p...
1106

1572ca2a8   Dmitry Torokhov   Input: fix lockin...
1107
  	seq_printf(seq, "N: Number=%u Name=%s", state->pos, handler->name);
ef7995f4e   Dmitry Torokhov   Input: implement ...
1108
1109
  	if (handler->filter)
  		seq_puts(seq, " (filter)");
969b21cde   Dmitry Torokhov   Input: convert /p...
1110
1111
1112
1113
1114
1115
1116
  	if (handler->fops)
  		seq_printf(seq, " Minor=%d", handler->minor);
  	seq_putc(seq, '
  ');
  
  	return 0;
  }
1572ca2a8   Dmitry Torokhov   Input: fix lockin...
1117

cec69c376   Jan Engelhardt   Input: constify f...
1118
  static const struct seq_operations input_handlers_seq_ops = {
969b21cde   Dmitry Torokhov   Input: convert /p...
1119
1120
  	.start	= input_handlers_seq_start,
  	.next	= input_handlers_seq_next,
1572ca2a8   Dmitry Torokhov   Input: fix lockin...
1121
  	.stop	= input_seq_stop,
969b21cde   Dmitry Torokhov   Input: convert /p...
1122
1123
1124
1125
1126
1127
1128
  	.show	= input_handlers_seq_show,
  };
  
  static int input_proc_handlers_open(struct inode *inode, struct file *file)
  {
  	return seq_open(file, &input_handlers_seq_ops);
  }
2b8693c06   Arjan van de Ven   [PATCH] mark stru...
1129
  static const struct file_operations input_handlers_fileops = {
969b21cde   Dmitry Torokhov   Input: convert /p...
1130
1131
1132
1133
1134
1135
  	.owner		= THIS_MODULE,
  	.open		= input_proc_handlers_open,
  	.read		= seq_read,
  	.llseek		= seq_lseek,
  	.release	= seq_release,
  };
f96b434d3   Dmitry Torokhov   Input: rearrange ...
1136
1137
1138
1139
  
  static int __init input_proc_init(void)
  {
  	struct proc_dir_entry *entry;
9c37066d8   Alexey Dobriyan   proc: remove proc...
1140
  	proc_bus_input_dir = proc_mkdir("bus/input", NULL);
f96b434d3   Dmitry Torokhov   Input: rearrange ...
1141
1142
  	if (!proc_bus_input_dir)
  		return -ENOMEM;
c7705f344   Denis V. Lunev   drivers: use non-...
1143
1144
  	entry = proc_create("devices", 0, proc_bus_input_dir,
  			    &input_devices_fileops);
f96b434d3   Dmitry Torokhov   Input: rearrange ...
1145
1146
  	if (!entry)
  		goto fail1;
c7705f344   Denis V. Lunev   drivers: use non-...
1147
1148
  	entry = proc_create("handlers", 0, proc_bus_input_dir,
  			    &input_handlers_fileops);
f96b434d3   Dmitry Torokhov   Input: rearrange ...
1149
1150
  	if (!entry)
  		goto fail2;
f96b434d3   Dmitry Torokhov   Input: rearrange ...
1151
1152
1153
  	return 0;
  
   fail2:	remove_proc_entry("devices", proc_bus_input_dir);
9c37066d8   Alexey Dobriyan   proc: remove proc...
1154
   fail1: remove_proc_entry("bus/input", NULL);
f96b434d3   Dmitry Torokhov   Input: rearrange ...
1155
1156
  	return -ENOMEM;
  }
beffbdc22   Andrew Morton   Input: cannot ref...
1157
  static void input_proc_exit(void)
f96b434d3   Dmitry Torokhov   Input: rearrange ...
1158
1159
1160
  {
  	remove_proc_entry("devices", proc_bus_input_dir);
  	remove_proc_entry("handlers", proc_bus_input_dir);
9c37066d8   Alexey Dobriyan   proc: remove proc...
1161
  	remove_proc_entry("bus/input", NULL);
f96b434d3   Dmitry Torokhov   Input: rearrange ...
1162
1163
1164
1165
1166
1167
1168
  }
  
  #else /* !CONFIG_PROC_FS */
  static inline void input_wakeup_procfs_readers(void) { }
  static inline int input_proc_init(void) { return 0; }
  static inline void input_proc_exit(void) { }
  #endif
9657d75c5   Dmitry Torokhov   Input: convert fr...
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
  #define INPUT_DEV_STRING_ATTR_SHOW(name)				\
  static ssize_t input_dev_show_##name(struct device *dev,		\
  				     struct device_attribute *attr,	\
  				     char *buf)				\
  {									\
  	struct input_dev *input_dev = to_input_dev(dev);		\
  									\
  	return scnprintf(buf, PAGE_SIZE, "%s
  ",			\
  			 input_dev->name ? input_dev->name : "");	\
  }									\
  static DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL)
5c1e9a6a6   Dmitry Torokhov   [PATCH] Input: ex...
1181
1182
1183
1184
  
  INPUT_DEV_STRING_ATTR_SHOW(name);
  INPUT_DEV_STRING_ATTR_SHOW(phys);
  INPUT_DEV_STRING_ATTR_SHOW(uniq);
ac648a6a7   Dmitry Torokhov   Input: make modal...
1185
1186
1187
  static int input_print_modalias_bits(char *buf, int size,
  				     char name, unsigned long *bm,
  				     unsigned int min_bit, unsigned int max_bit)
1d8f430c1   Rusty Russell   [PATCH] Input: ad...
1188
  {
ac648a6a7   Dmitry Torokhov   Input: make modal...
1189
  	int len = 0, i;
1d8f430c1   Rusty Russell   [PATCH] Input: ad...
1190

ac648a6a7   Dmitry Torokhov   Input: make modal...
1191
1192
  	len += snprintf(buf, max(size, 0), "%c", name);
  	for (i = min_bit; i < max_bit; i++)
7b19ada2e   Jiri Slaby   get rid of input ...
1193
  		if (bm[BIT_WORD(i)] & BIT_MASK(i))
ac648a6a7   Dmitry Torokhov   Input: make modal...
1194
  			len += snprintf(buf + len, max(size - len, 0), "%X,", i);
1d8f430c1   Rusty Russell   [PATCH] Input: ad...
1195
1196
  	return len;
  }
2db668763   Dmitry Torokhov   Input: limit attr...
1197
1198
  static int input_print_modalias(char *buf, int size, struct input_dev *id,
  				int add_cr)
1d8f430c1   Rusty Russell   [PATCH] Input: ad...
1199
  {
bd37e5a95   Kay Sievers   [PATCH] INPUT: ad...
1200
  	int len;
1d8f430c1   Rusty Russell   [PATCH] Input: ad...
1201

ac648a6a7   Dmitry Torokhov   Input: make modal...
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
  	len = snprintf(buf, max(size, 0),
  		       "input:b%04Xv%04Xp%04Xe%04X-",
  		       id->id.bustype, id->id.vendor,
  		       id->id.product, id->id.version);
  
  	len += input_print_modalias_bits(buf + len, size - len,
  				'e', id->evbit, 0, EV_MAX);
  	len += input_print_modalias_bits(buf + len, size - len,
  				'k', id->keybit, KEY_MIN_INTERESTING, KEY_MAX);
  	len += input_print_modalias_bits(buf + len, size - len,
  				'r', id->relbit, 0, REL_MAX);
  	len += input_print_modalias_bits(buf + len, size - len,
  				'a', id->absbit, 0, ABS_MAX);
  	len += input_print_modalias_bits(buf + len, size - len,
  				'm', id->mscbit, 0, MSC_MAX);
  	len += input_print_modalias_bits(buf + len, size - len,
  				'l', id->ledbit, 0, LED_MAX);
  	len += input_print_modalias_bits(buf + len, size - len,
  				's', id->sndbit, 0, SND_MAX);
  	len += input_print_modalias_bits(buf + len, size - len,
  				'f', id->ffbit, 0, FF_MAX);
  	len += input_print_modalias_bits(buf + len, size - len,
  				'w', id->swbit, 0, SW_MAX);
2db668763   Dmitry Torokhov   Input: limit attr...
1225
1226
  
  	if (add_cr)
ac648a6a7   Dmitry Torokhov   Input: make modal...
1227
1228
  		len += snprintf(buf + len, max(size - len, 0), "
  ");
2db668763   Dmitry Torokhov   Input: limit attr...
1229

bd37e5a95   Kay Sievers   [PATCH] INPUT: ad...
1230
1231
  	return len;
  }
9657d75c5   Dmitry Torokhov   Input: convert fr...
1232
1233
1234
  static ssize_t input_dev_show_modalias(struct device *dev,
  				       struct device_attribute *attr,
  				       char *buf)
bd37e5a95   Kay Sievers   [PATCH] INPUT: ad...
1235
1236
1237
  {
  	struct input_dev *id = to_input_dev(dev);
  	ssize_t len;
2db668763   Dmitry Torokhov   Input: limit attr...
1238
  	len = input_print_modalias(buf, PAGE_SIZE, id, 1);
8a3cf456a   Richard Purdie   Input: return cor...
1239
  	return min_t(int, len, PAGE_SIZE);
1d8f430c1   Rusty Russell   [PATCH] Input: ad...
1240
  }
9657d75c5   Dmitry Torokhov   Input: convert fr...
1241
  static DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
1d8f430c1   Rusty Russell   [PATCH] Input: ad...
1242

85b772003   Henrik Rydberg   Input: introduce ...
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
  static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap,
  			      int max, int add_cr);
  
  static ssize_t input_dev_show_properties(struct device *dev,
  					 struct device_attribute *attr,
  					 char *buf)
  {
  	struct input_dev *input_dev = to_input_dev(dev);
  	int len = input_print_bitmap(buf, PAGE_SIZE, input_dev->propbit,
  				     INPUT_PROP_MAX, true);
  	return min_t(int, len, PAGE_SIZE);
  }
  static DEVICE_ATTR(properties, S_IRUGO, input_dev_show_properties, NULL);
629b77a42   Greg Kroah-Hartman   [PATCH] INPUT: Fi...
1256
  static struct attribute *input_dev_attrs[] = {
9657d75c5   Dmitry Torokhov   Input: convert fr...
1257
1258
1259
1260
  	&dev_attr_name.attr,
  	&dev_attr_phys.attr,
  	&dev_attr_uniq.attr,
  	&dev_attr_modalias.attr,
85b772003   Henrik Rydberg   Input: introduce ...
1261
  	&dev_attr_properties.attr,
629b77a42   Greg Kroah-Hartman   [PATCH] INPUT: Fi...
1262
1263
  	NULL
  };
bd0ef2356   Dmitry Torokhov   Input: handle fai...
1264
  static struct attribute_group input_dev_attr_group = {
629b77a42   Greg Kroah-Hartman   [PATCH] INPUT: Fi...
1265
  	.attrs	= input_dev_attrs,
5c1e9a6a6   Dmitry Torokhov   [PATCH] Input: ex...
1266
  };
9657d75c5   Dmitry Torokhov   Input: convert fr...
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
  #define INPUT_DEV_ID_ATTR(name)						\
  static ssize_t input_dev_show_id_##name(struct device *dev,		\
  					struct device_attribute *attr,	\
  					char *buf)			\
  {									\
  	struct input_dev *input_dev = to_input_dev(dev);		\
  	return scnprintf(buf, PAGE_SIZE, "%04x
  ", input_dev->id.name);	\
  }									\
  static DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL)
5c1e9a6a6   Dmitry Torokhov   [PATCH] Input: ex...
1277
1278
1279
1280
1281
1282
1283
  
  INPUT_DEV_ID_ATTR(bustype);
  INPUT_DEV_ID_ATTR(vendor);
  INPUT_DEV_ID_ATTR(product);
  INPUT_DEV_ID_ATTR(version);
  
  static struct attribute *input_dev_id_attrs[] = {
9657d75c5   Dmitry Torokhov   Input: convert fr...
1284
1285
1286
1287
  	&dev_attr_bustype.attr,
  	&dev_attr_vendor.attr,
  	&dev_attr_product.attr,
  	&dev_attr_version.attr,
5c1e9a6a6   Dmitry Torokhov   [PATCH] Input: ex...
1288
1289
1290
1291
1292
1293
1294
  	NULL
  };
  
  static struct attribute_group input_dev_id_attr_group = {
  	.name	= "id",
  	.attrs	= input_dev_id_attrs,
  };
969b21cde   Dmitry Torokhov   Input: convert /p...
1295
1296
1297
1298
1299
  static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap,
  			      int max, int add_cr)
  {
  	int i;
  	int len = 0;
15e184afa   Dmitry Torokhov   Input: add compat...
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
  	bool skip_empty = true;
  
  	for (i = BITS_TO_LONGS(max) - 1; i >= 0; i--) {
  		len += input_bits_to_string(buf + len, max(buf_size - len, 0),
  					    bitmap[i], skip_empty);
  		if (len) {
  			skip_empty = false;
  			if (i > 0)
  				len += snprintf(buf + len, max(buf_size - len, 0), " ");
  		}
  	}
969b21cde   Dmitry Torokhov   Input: convert /p...
1311

15e184afa   Dmitry Torokhov   Input: add compat...
1312
1313
1314
1315
1316
  	/*
  	 * If no output was produced print a single 0.
  	 */
  	if (len == 0)
  		len = snprintf(buf, buf_size, "%d", 0);
969b21cde   Dmitry Torokhov   Input: convert /p...
1317
1318
1319
1320
1321
1322
1323
  
  	if (add_cr)
  		len += snprintf(buf + len, max(buf_size - len, 0), "
  ");
  
  	return len;
  }
9657d75c5   Dmitry Torokhov   Input: convert fr...
1324
1325
1326
1327
1328
1329
1330
  #define INPUT_DEV_CAP_ATTR(ev, bm)					\
  static ssize_t input_dev_show_cap_##bm(struct device *dev,		\
  				       struct device_attribute *attr,	\
  				       char *buf)			\
  {									\
  	struct input_dev *input_dev = to_input_dev(dev);		\
  	int len = input_print_bitmap(buf, PAGE_SIZE,			\
15e184afa   Dmitry Torokhov   Input: add compat...
1331
1332
  				     input_dev->bm##bit, ev##_MAX,	\
  				     true);				\
9657d75c5   Dmitry Torokhov   Input: convert fr...
1333
1334
1335
  	return min_t(int, len, PAGE_SIZE);				\
  }									\
  static DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL)
5c1e9a6a6   Dmitry Torokhov   [PATCH] Input: ex...
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
  
  INPUT_DEV_CAP_ATTR(EV, ev);
  INPUT_DEV_CAP_ATTR(KEY, key);
  INPUT_DEV_CAP_ATTR(REL, rel);
  INPUT_DEV_CAP_ATTR(ABS, abs);
  INPUT_DEV_CAP_ATTR(MSC, msc);
  INPUT_DEV_CAP_ATTR(LED, led);
  INPUT_DEV_CAP_ATTR(SND, snd);
  INPUT_DEV_CAP_ATTR(FF, ff);
  INPUT_DEV_CAP_ATTR(SW, sw);
  
  static struct attribute *input_dev_caps_attrs[] = {
9657d75c5   Dmitry Torokhov   Input: convert fr...
1348
1349
1350
1351
1352
1353
1354
1355
1356
  	&dev_attr_ev.attr,
  	&dev_attr_key.attr,
  	&dev_attr_rel.attr,
  	&dev_attr_abs.attr,
  	&dev_attr_msc.attr,
  	&dev_attr_led.attr,
  	&dev_attr_snd.attr,
  	&dev_attr_ff.attr,
  	&dev_attr_sw.attr,
5c1e9a6a6   Dmitry Torokhov   [PATCH] Input: ex...
1357
1358
1359
1360
1361
1362
1363
  	NULL
  };
  
  static struct attribute_group input_dev_caps_attr_group = {
  	.name	= "capabilities",
  	.attrs	= input_dev_caps_attrs,
  };
a4dbd6740   David Brownell   driver model: con...
1364
  static const struct attribute_group *input_dev_attr_groups[] = {
cb9def4df   Dmitry Torokhov   Input: let driver...
1365
1366
1367
1368
1369
  	&input_dev_attr_group,
  	&input_dev_id_attr_group,
  	&input_dev_caps_attr_group,
  	NULL
  };
9657d75c5   Dmitry Torokhov   Input: convert fr...
1370
  static void input_dev_release(struct device *device)
d19fbe8a7   Dmitry Torokhov   [PATCH] Input: pr...
1371
  {
9657d75c5   Dmitry Torokhov   Input: convert fr...
1372
  	struct input_dev *dev = to_input_dev(device);
d19fbe8a7   Dmitry Torokhov   [PATCH] Input: pr...
1373

509ca1a93   Anssi Hannula   Input: implement ...
1374
  	input_ff_destroy(dev);
40d007e7d   Henrik Rydberg   Input: introduce ...
1375
  	input_mt_destroy_slots(dev);
d31b2865a   Daniel Mack   Input: dynamicall...
1376
  	kfree(dev->absinfo);
d19fbe8a7   Dmitry Torokhov   [PATCH] Input: pr...
1377
  	kfree(dev);
509ca1a93   Anssi Hannula   Input: implement ...
1378

d19fbe8a7   Dmitry Torokhov   [PATCH] Input: pr...
1379
1380
  	module_put(THIS_MODULE);
  }
a7fadbe10   Dmitry Torokhov   [PATCH] input cor...
1381
  /*
312c004d3   Kay Sievers   [PATCH] driver co...
1382
   * Input uevent interface - loading event handlers based on
a7fadbe10   Dmitry Torokhov   [PATCH] input cor...
1383
1384
   * device bitfields.
   */
7eff2e7a8   Kay Sievers   Driver core: chan...
1385
  static int input_add_uevent_bm_var(struct kobj_uevent_env *env,
ac648a6a7   Dmitry Torokhov   Input: make modal...
1386
  				   const char *name, unsigned long *bitmap, int max)
a7fadbe10   Dmitry Torokhov   [PATCH] input cor...
1387
  {
7eff2e7a8   Kay Sievers   Driver core: chan...
1388
  	int len;
a7fadbe10   Dmitry Torokhov   [PATCH] input cor...
1389

fcd3027ab   Henrik Rydberg   Input: fix double...
1390
  	if (add_uevent_var(env, "%s", name))
a7fadbe10   Dmitry Torokhov   [PATCH] input cor...
1391
  		return -ENOMEM;
7eff2e7a8   Kay Sievers   Driver core: chan...
1392
1393
  	len = input_print_bitmap(&env->buf[env->buflen - 1],
  				 sizeof(env->buf) - env->buflen,
15e184afa   Dmitry Torokhov   Input: add compat...
1394
  				 bitmap, max, false);
7eff2e7a8   Kay Sievers   Driver core: chan...
1395
  	if (len >= (sizeof(env->buf) - env->buflen))
a7fadbe10   Dmitry Torokhov   [PATCH] input cor...
1396
  		return -ENOMEM;
7eff2e7a8   Kay Sievers   Driver core: chan...
1397
  	env->buflen += len;
a7fadbe10   Dmitry Torokhov   [PATCH] input cor...
1398
1399
  	return 0;
  }
7eff2e7a8   Kay Sievers   Driver core: chan...
1400
  static int input_add_uevent_modalias_var(struct kobj_uevent_env *env,
ac648a6a7   Dmitry Torokhov   Input: make modal...
1401
1402
  					 struct input_dev *dev)
  {
7eff2e7a8   Kay Sievers   Driver core: chan...
1403
  	int len;
ac648a6a7   Dmitry Torokhov   Input: make modal...
1404

7eff2e7a8   Kay Sievers   Driver core: chan...
1405
  	if (add_uevent_var(env, "MODALIAS="))
ac648a6a7   Dmitry Torokhov   Input: make modal...
1406
  		return -ENOMEM;
7eff2e7a8   Kay Sievers   Driver core: chan...
1407
1408
1409
1410
  	len = input_print_modalias(&env->buf[env->buflen - 1],
  				   sizeof(env->buf) - env->buflen,
  				   dev, 0);
  	if (len >= (sizeof(env->buf) - env->buflen))
ac648a6a7   Dmitry Torokhov   Input: make modal...
1411
  		return -ENOMEM;
7eff2e7a8   Kay Sievers   Driver core: chan...
1412
  	env->buflen += len;
ac648a6a7   Dmitry Torokhov   Input: make modal...
1413
1414
  	return 0;
  }
a7fadbe10   Dmitry Torokhov   [PATCH] input cor...
1415
1416
  #define INPUT_ADD_HOTPLUG_VAR(fmt, val...)				\
  	do {								\
7eff2e7a8   Kay Sievers   Driver core: chan...
1417
  		int err = add_uevent_var(env, fmt, val);		\
a7fadbe10   Dmitry Torokhov   [PATCH] input cor...
1418
1419
1420
1421
1422
1423
  		if (err)						\
  			return err;					\
  	} while (0)
  
  #define INPUT_ADD_HOTPLUG_BM_VAR(name, bm, max)				\
  	do {								\
7eff2e7a8   Kay Sievers   Driver core: chan...
1424
  		int err = input_add_uevent_bm_var(env, name, bm, max);	\
a7fadbe10   Dmitry Torokhov   [PATCH] input cor...
1425
1426
1427
  		if (err)						\
  			return err;					\
  	} while (0)
ac648a6a7   Dmitry Torokhov   Input: make modal...
1428
1429
  #define INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev)				\
  	do {								\
7eff2e7a8   Kay Sievers   Driver core: chan...
1430
  		int err = input_add_uevent_modalias_var(env, dev);	\
ac648a6a7   Dmitry Torokhov   Input: make modal...
1431
1432
1433
  		if (err)						\
  			return err;					\
  	} while (0)
7eff2e7a8   Kay Sievers   Driver core: chan...
1434
  static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env)
a7fadbe10   Dmitry Torokhov   [PATCH] input cor...
1435
  {
9657d75c5   Dmitry Torokhov   Input: convert fr...
1436
  	struct input_dev *dev = to_input_dev(device);
a7fadbe10   Dmitry Torokhov   [PATCH] input cor...
1437
1438
1439
1440
1441
1442
1443
1444
  
  	INPUT_ADD_HOTPLUG_VAR("PRODUCT=%x/%x/%x/%x",
  				dev->id.bustype, dev->id.vendor,
  				dev->id.product, dev->id.version);
  	if (dev->name)
  		INPUT_ADD_HOTPLUG_VAR("NAME=\"%s\"", dev->name);
  	if (dev->phys)
  		INPUT_ADD_HOTPLUG_VAR("PHYS=\"%s\"", dev->phys);
08de1f046   Dmitry Torokhov   [PATCH] Input: fi...
1445
  	if (dev->uniq)
a7fadbe10   Dmitry Torokhov   [PATCH] input cor...
1446
  		INPUT_ADD_HOTPLUG_VAR("UNIQ=\"%s\"", dev->uniq);
85b772003   Henrik Rydberg   Input: introduce ...
1447
  	INPUT_ADD_HOTPLUG_BM_VAR("PROP=", dev->propbit, INPUT_PROP_MAX);
a7fadbe10   Dmitry Torokhov   [PATCH] input cor...
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
  	INPUT_ADD_HOTPLUG_BM_VAR("EV=", dev->evbit, EV_MAX);
  	if (test_bit(EV_KEY, dev->evbit))
  		INPUT_ADD_HOTPLUG_BM_VAR("KEY=", dev->keybit, KEY_MAX);
  	if (test_bit(EV_REL, dev->evbit))
  		INPUT_ADD_HOTPLUG_BM_VAR("REL=", dev->relbit, REL_MAX);
  	if (test_bit(EV_ABS, dev->evbit))
  		INPUT_ADD_HOTPLUG_BM_VAR("ABS=", dev->absbit, ABS_MAX);
  	if (test_bit(EV_MSC, dev->evbit))
  		INPUT_ADD_HOTPLUG_BM_VAR("MSC=", dev->mscbit, MSC_MAX);
  	if (test_bit(EV_LED, dev->evbit))
  		INPUT_ADD_HOTPLUG_BM_VAR("LED=", dev->ledbit, LED_MAX);
  	if (test_bit(EV_SND, dev->evbit))
  		INPUT_ADD_HOTPLUG_BM_VAR("SND=", dev->sndbit, SND_MAX);
  	if (test_bit(EV_FF, dev->evbit))
  		INPUT_ADD_HOTPLUG_BM_VAR("FF=", dev->ffbit, FF_MAX);
  	if (test_bit(EV_SW, dev->evbit))
  		INPUT_ADD_HOTPLUG_BM_VAR("SW=", dev->swbit, SW_MAX);
ac648a6a7   Dmitry Torokhov   Input: make modal...
1465
  	INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev);
a7fadbe10   Dmitry Torokhov   [PATCH] input cor...
1466
1467
1468
  
  	return 0;
  }
3cc963517   Dmitry Torokhov   Input: force LED ...
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
  #define INPUT_DO_TOGGLE(dev, type, bits, on)				\
  	do {								\
  		int i;							\
  		bool active;						\
  									\
  		if (!test_bit(EV_##type, dev->evbit))			\
  			break;						\
  									\
  		for (i = 0; i < type##_MAX; i++) {			\
  			if (!test_bit(i, dev->bits##bit))		\
  				continue;				\
  									\
  			active = test_bit(i, dev->bits);		\
  			if (!active && !on)				\
  				continue;				\
  									\
  			dev->event(dev, EV_##type, i, on ? active : 0);	\
  		}							\
ffd0db971   Dmitry Torokhov   Input: add generi...
1487
  	} while (0)
b50b52169   Dmitry Torokhov   Input: export inp...
1488
  static void input_dev_toggle(struct input_dev *dev, bool activate)
ffd0db971   Dmitry Torokhov   Input: add generi...
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
  {
  	if (!dev->event)
  		return;
  
  	INPUT_DO_TOGGLE(dev, LED, led, activate);
  	INPUT_DO_TOGGLE(dev, SND, snd, activate);
  
  	if (activate && test_bit(EV_REP, dev->evbit)) {
  		dev->event(dev, EV_REP, REP_PERIOD, dev->rep[REP_PERIOD]);
  		dev->event(dev, EV_REP, REP_DELAY, dev->rep[REP_DELAY]);
  	}
  }
b50b52169   Dmitry Torokhov   Input: export inp...
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
  /**
   * input_reset_device() - reset/restore the state of input device
   * @dev: input device whose state needs to be reset
   *
   * This function tries to reset the state of an opened input device and
   * bring internal state and state if the hardware in sync with each other.
   * We mark all keys as released, restore LED state, repeat rate, etc.
   */
  void input_reset_device(struct input_dev *dev)
  {
  	mutex_lock(&dev->mutex);
  
  	if (dev->users) {
  		input_dev_toggle(dev, true);
  
  		/*
  		 * Keys that have been pressed at suspend time are unlikely
  		 * to be still pressed when we resume.
  		 */
  		spin_lock_irq(&dev->event_lock);
  		input_dev_release_keys(dev);
  		spin_unlock_irq(&dev->event_lock);
  	}
  
  	mutex_unlock(&dev->mutex);
  }
  EXPORT_SYMBOL(input_reset_device);
  
  #ifdef CONFIG_PM
ffd0db971   Dmitry Torokhov   Input: add generi...
1530
1531
1532
1533
1534
  static int input_dev_suspend(struct device *dev)
  {
  	struct input_dev *input_dev = to_input_dev(dev);
  
  	mutex_lock(&input_dev->mutex);
b50b52169   Dmitry Torokhov   Input: export inp...
1535
1536
1537
  
  	if (input_dev->users)
  		input_dev_toggle(input_dev, false);
ffd0db971   Dmitry Torokhov   Input: add generi...
1538
1539
1540
1541
1542
1543
1544
1545
  	mutex_unlock(&input_dev->mutex);
  
  	return 0;
  }
  
  static int input_dev_resume(struct device *dev)
  {
  	struct input_dev *input_dev = to_input_dev(dev);
b50b52169   Dmitry Torokhov   Input: export inp...
1546
  	input_reset_device(input_dev);
ffd0db971   Dmitry Torokhov   Input: add generi...
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
  
  	return 0;
  }
  
  static const struct dev_pm_ops input_dev_pm_ops = {
  	.suspend	= input_dev_suspend,
  	.resume		= input_dev_resume,
  	.poweroff	= input_dev_suspend,
  	.restore	= input_dev_resume,
  };
  #endif /* CONFIG_PM */
9657d75c5   Dmitry Torokhov   Input: convert fr...
1558
1559
1560
1561
  static struct device_type input_dev_type = {
  	.groups		= input_dev_attr_groups,
  	.release	= input_dev_release,
  	.uevent		= input_dev_uevent,
ffd0db971   Dmitry Torokhov   Input: add generi...
1562
1563
1564
  #ifdef CONFIG_PM
  	.pm		= &input_dev_pm_ops,
  #endif
9657d75c5   Dmitry Torokhov   Input: convert fr...
1565
  };
2c9ede55e   Al Viro   switch device_get...
1566
  static char *input_devnode(struct device *dev, umode_t *mode)
aa5ed63e9   Kay Sievers   Driver Core: inpu...
1567
1568
1569
  {
  	return kasprintf(GFP_KERNEL, "input/%s", dev_name(dev));
  }
ea9f240bd   Greg Kroah-Hartman   [PATCH] INPUT: re...
1570
  struct class input_class = {
9657d75c5   Dmitry Torokhov   Input: convert fr...
1571
  	.name		= "input",
e454cea20   Kay Sievers   Driver-Core: exte...
1572
  	.devnode	= input_devnode,
d19fbe8a7   Dmitry Torokhov   [PATCH] Input: pr...
1573
  };
ca56fe07f   Dmitry Torokhov   Input: rearrange ...
1574
  EXPORT_SYMBOL_GPL(input_class);
d19fbe8a7   Dmitry Torokhov   [PATCH] Input: pr...
1575

1447190e3   Dmitry Torokhov   Input: add commen...
1576
1577
1578
1579
1580
1581
1582
1583
1584
  /**
   * input_allocate_device - allocate memory for new input device
   *
   * Returns prepared struct input_dev or NULL.
   *
   * NOTE: Use input_free_device() to free devices that have not been
   * registered; input_unregister_device() should be used for already
   * registered devices.
   */
d19fbe8a7   Dmitry Torokhov   [PATCH] Input: pr...
1585
1586
1587
1588
1589
1590
  struct input_dev *input_allocate_device(void)
  {
  	struct input_dev *dev;
  
  	dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
  	if (dev) {
9657d75c5   Dmitry Torokhov   Input: convert fr...
1591
1592
1593
  		dev->dev.type = &input_dev_type;
  		dev->dev.class = &input_class;
  		device_initialize(&dev->dev);
f60d2b111   Dmitry Torokhov   Input: reset name...
1594
  		mutex_init(&dev->mutex);
8006479c9   Dmitry Torokhov   Input: implement ...
1595
  		spin_lock_init(&dev->event_lock);
d19fbe8a7   Dmitry Torokhov   [PATCH] Input: pr...
1596
1597
  		INIT_LIST_HEAD(&dev->h_list);
  		INIT_LIST_HEAD(&dev->node);
655816e49   Dmitry Torokhov   Input: fix input ...
1598
1599
  
  		__module_get(THIS_MODULE);
d19fbe8a7   Dmitry Torokhov   [PATCH] Input: pr...
1600
1601
1602
1603
  	}
  
  	return dev;
  }
ca56fe07f   Dmitry Torokhov   Input: rearrange ...
1604
  EXPORT_SYMBOL(input_allocate_device);
d19fbe8a7   Dmitry Torokhov   [PATCH] Input: pr...
1605

1447190e3   Dmitry Torokhov   Input: add commen...
1606
1607
1608
1609
1610
1611
1612
  /**
   * input_free_device - free memory occupied by input_dev structure
   * @dev: input device to free
   *
   * This function should only be used if input_register_device()
   * was not called yet or if it failed. Once device was registered
   * use input_unregister_device() and memory will be freed once last
8006479c9   Dmitry Torokhov   Input: implement ...
1613
   * reference to the device is dropped.
1447190e3   Dmitry Torokhov   Input: add commen...
1614
1615
1616
1617
1618
1619
   *
   * Device should be allocated by input_allocate_device().
   *
   * NOTE: If there are references to the input device then memory
   * will not be freed until last reference is dropped.
   */
f60d2b111   Dmitry Torokhov   Input: reset name...
1620
1621
  void input_free_device(struct input_dev *dev)
  {
54f9e36cb   Dmitry Torokhov   Input: simplify i...
1622
  	if (dev)
f60d2b111   Dmitry Torokhov   Input: reset name...
1623
  		input_put_device(dev);
f60d2b111   Dmitry Torokhov   Input: reset name...
1624
  }
ca56fe07f   Dmitry Torokhov   Input: rearrange ...
1625
  EXPORT_SYMBOL(input_free_device);
f60d2b111   Dmitry Torokhov   Input: reset name...
1626

534565f25   Dmitry Torokhov   Input: add input_...
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
  /**
   * input_set_capability - mark device as capable of a certain event
   * @dev: device that is capable of emitting or accepting event
   * @type: type of the event (EV_KEY, EV_REL, etc...)
   * @code: event code
   *
   * In addition to setting up corresponding bit in appropriate capability
   * bitmap the function also adjusts dev->evbit.
   */
  void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code)
  {
  	switch (type) {
  	case EV_KEY:
  		__set_bit(code, dev->keybit);
  		break;
  
  	case EV_REL:
  		__set_bit(code, dev->relbit);
  		break;
  
  	case EV_ABS:
  		__set_bit(code, dev->absbit);
  		break;
  
  	case EV_MSC:
  		__set_bit(code, dev->mscbit);
  		break;
  
  	case EV_SW:
  		__set_bit(code, dev->swbit);
  		break;
  
  	case EV_LED:
  		__set_bit(code, dev->ledbit);
  		break;
  
  	case EV_SND:
  		__set_bit(code, dev->sndbit);
  		break;
  
  	case EV_FF:
  		__set_bit(code, dev->ffbit);
  		break;
22d1c398e   Dmitry Eremin-Solenikov   Input: Handle EV_...
1670
1671
1672
  	case EV_PWR:
  		/* do nothing */
  		break;
534565f25   Dmitry Torokhov   Input: add input_...
1673
  	default:
da0c49011   Joe Perches   Input: use pr_fmt...
1674
1675
1676
  		pr_err("input_set_capability: unknown type %u (code %u)
  ",
  		       type, code);
534565f25   Dmitry Torokhov   Input: add input_...
1677
1678
1679
1680
1681
1682
1683
  		dump_stack();
  		return;
  	}
  
  	__set_bit(type, dev->evbit);
  }
  EXPORT_SYMBOL(input_set_capability);
80b4895aa   Jeff Brown   Input: estimate n...
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
  static unsigned int input_estimate_events_per_packet(struct input_dev *dev)
  {
  	int mt_slots;
  	int i;
  	unsigned int events;
  
  	if (dev->mtsize) {
  		mt_slots = dev->mtsize;
  	} else if (test_bit(ABS_MT_TRACKING_ID, dev->absbit)) {
  		mt_slots = dev->absinfo[ABS_MT_TRACKING_ID].maximum -
  			   dev->absinfo[ABS_MT_TRACKING_ID].minimum + 1,
8c127f071   Hans Petter Selasky   Input: properly a...
1695
  		mt_slots = clamp(mt_slots, 2, 32);
80b4895aa   Jeff Brown   Input: estimate n...
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
  	} else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
  		mt_slots = 2;
  	} else {
  		mt_slots = 0;
  	}
  
  	events = mt_slots + 1; /* count SYN_MT_REPORT and SYN_REPORT */
  
  	for (i = 0; i < ABS_CNT; i++) {
  		if (test_bit(i, dev->absbit)) {
  			if (input_is_mt_axis(i))
  				events += mt_slots;
  			else
  				events++;
  		}
  	}
  
  	for (i = 0; i < REL_CNT; i++)
  		if (test_bit(i, dev->relbit))
  			events++;
  
  	return events;
  }
92a3a5878   Dmitry Torokhov   Input: cleanse ca...
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
  #define INPUT_CLEANSE_BITMASK(dev, type, bits)				\
  	do {								\
  		if (!test_bit(EV_##type, dev->evbit))			\
  			memset(dev->bits##bit, 0,			\
  				sizeof(dev->bits##bit));		\
  	} while (0)
  
  static void input_cleanse_bitmasks(struct input_dev *dev)
  {
  	INPUT_CLEANSE_BITMASK(dev, KEY, key);
  	INPUT_CLEANSE_BITMASK(dev, REL, rel);
  	INPUT_CLEANSE_BITMASK(dev, ABS, abs);
  	INPUT_CLEANSE_BITMASK(dev, MSC, msc);
  	INPUT_CLEANSE_BITMASK(dev, LED, led);
  	INPUT_CLEANSE_BITMASK(dev, SND, snd);
  	INPUT_CLEANSE_BITMASK(dev, FF, ff);
  	INPUT_CLEANSE_BITMASK(dev, SW, sw);
  }
8006479c9   Dmitry Torokhov   Input: implement ...
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
  /**
   * input_register_device - register device with input core
   * @dev: device to be registered
   *
   * This function registers device with input core. The device must be
   * allocated with input_allocate_device() and all it's capabilities
   * set up before registering.
   * If function fails the device must be freed with input_free_device().
   * Once device has been successfully registered it can be unregistered
   * with input_unregister_device(); input_free_device() should not be
   * called in this case.
   */
5f9454898   Dmitry Torokhov   Input: do not reg...
1749
  int input_register_device(struct input_dev *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1750
  {
bd0ef2356   Dmitry Torokhov   Input: handle fai...
1751
  	static atomic_t input_no = ATOMIC_INIT(0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1752
  	struct input_handler *handler;
bd0ef2356   Dmitry Torokhov   Input: handle fai...
1753
1754
  	const char *path;
  	int error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1755

4f93df408   Dmitry Torokhov   Input: automatica...
1756
  	/* Every input device generates EV_SYN/SYN_REPORT events. */
8006479c9   Dmitry Torokhov   Input: implement ...
1757
  	__set_bit(EV_SYN, dev->evbit);
0fbf87caf   Dmitry Torokhov   Input: add semaph...
1758

4f93df408   Dmitry Torokhov   Input: automatica...
1759
1760
  	/* KEY_RESERVED is not supposed to be transmitted to userspace. */
  	__clear_bit(KEY_RESERVED, dev->keybit);
92a3a5878   Dmitry Torokhov   Input: cleanse ca...
1761
1762
  	/* Make sure that bitmasks not mentioned in dev->evbit are clean. */
  	input_cleanse_bitmasks(dev);
80b4895aa   Jeff Brown   Input: estimate n...
1763
1764
1765
  	if (!dev->hint_events_per_packet)
  		dev->hint_events_per_packet =
  				input_estimate_events_per_packet(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1766
1767
1768
1769
  	/*
  	 * If delay and period are pre-set by the driver, then autorepeating
  	 * is handled by the driver itself and we don't do it in input.c.
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1770
1771
1772
1773
1774
1775
1776
  	init_timer(&dev->timer);
  	if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {
  		dev->timer.data = (long) dev;
  		dev->timer.function = input_repeat_key;
  		dev->rep[REP_DELAY] = 250;
  		dev->rep[REP_PERIOD] = 33;
  	}
aebd636bd   Dmitry Torokhov   Input: switch com...
1777
1778
  	if (!dev->getkeycode)
  		dev->getkeycode = input_default_getkeycode;
c8e4c7727   Marvin Raaijmakers   Input: add getkey...
1779

aebd636bd   Dmitry Torokhov   Input: switch com...
1780
1781
  	if (!dev->setkeycode)
  		dev->setkeycode = input_default_setkeycode;
c8e4c7727   Marvin Raaijmakers   Input: add getkey...
1782

a6c2490f0   Kay Sievers   Input: struct dev...
1783
1784
  	dev_set_name(&dev->dev, "input%ld",
  		     (unsigned long) atomic_inc_return(&input_no) - 1);
bd0ef2356   Dmitry Torokhov   Input: handle fai...
1785

9657d75c5   Dmitry Torokhov   Input: convert fr...
1786
  	error = device_add(&dev->dev);
bd0ef2356   Dmitry Torokhov   Input: handle fai...
1787
1788
  	if (error)
  		return error;
9657d75c5   Dmitry Torokhov   Input: convert fr...
1789
  	path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
da0c49011   Joe Perches   Input: use pr_fmt...
1790
1791
1792
1793
  	pr_info("%s as %s
  ",
  		dev->name ? dev->name : "Unspecified device",
  		path ? path : "N/A");
bd0ef2356   Dmitry Torokhov   Input: handle fai...
1794
  	kfree(path);
102040204   Greg Kroah-Hartman   [PATCH] INPUT: re...
1795

8006479c9   Dmitry Torokhov   Input: implement ...
1796
1797
1798
1799
1800
1801
1802
  	error = mutex_lock_interruptible(&input_mutex);
  	if (error) {
  		device_del(&dev->dev);
  		return error;
  	}
  
  	list_add_tail(&dev->node, &input_dev_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1803
  	list_for_each_entry(handler, &input_handler_list, node)
5b2a08262   Dmitry Torokhov   Input: rework han...
1804
  		input_attach_handler(dev, handler);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1805

f96b434d3   Dmitry Torokhov   Input: rearrange ...
1806
  	input_wakeup_procfs_readers();
5f9454898   Dmitry Torokhov   Input: do not reg...
1807

8006479c9   Dmitry Torokhov   Input: implement ...
1808
  	mutex_unlock(&input_mutex);
5f9454898   Dmitry Torokhov   Input: do not reg...
1809
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1810
  }
ca56fe07f   Dmitry Torokhov   Input: rearrange ...
1811
  EXPORT_SYMBOL(input_register_device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1812

8006479c9   Dmitry Torokhov   Input: implement ...
1813
1814
1815
1816
1817
1818
1819
  /**
   * input_unregister_device - unregister previously registered device
   * @dev: device to be unregistered
   *
   * This function unregisters an input device. Once device is unregistered
   * the caller should not try to access it as it may get freed at any moment.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1820
1821
  void input_unregister_device(struct input_dev *dev)
  {
5b2a08262   Dmitry Torokhov   Input: rework han...
1822
  	struct input_handle *handle, *next;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1823

8006479c9   Dmitry Torokhov   Input: implement ...
1824
  	input_disconnect_device(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1825

8006479c9   Dmitry Torokhov   Input: implement ...
1826
  	mutex_lock(&input_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1827

5b2a08262   Dmitry Torokhov   Input: rework han...
1828
  	list_for_each_entry_safe(handle, next, &dev->h_list, d_node)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1829
  		handle->handler->disconnect(handle);
5b2a08262   Dmitry Torokhov   Input: rework han...
1830
  	WARN_ON(!list_empty(&dev->h_list));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1831

8006479c9   Dmitry Torokhov   Input: implement ...
1832
  	del_timer_sync(&dev->timer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1833
  	list_del_init(&dev->node);
f96b434d3   Dmitry Torokhov   Input: rearrange ...
1834
  	input_wakeup_procfs_readers();
8006479c9   Dmitry Torokhov   Input: implement ...
1835
1836
1837
1838
  
  	mutex_unlock(&input_mutex);
  
  	device_unregister(&dev->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1839
  }
ca56fe07f   Dmitry Torokhov   Input: rearrange ...
1840
  EXPORT_SYMBOL(input_unregister_device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1841

8006479c9   Dmitry Torokhov   Input: implement ...
1842
1843
1844
1845
1846
1847
1848
1849
  /**
   * input_register_handler - register a new input handler
   * @handler: handler to be registered
   *
   * This function registers a new input handler (interface) for input
   * devices in the system and attaches it to all input devices that
   * are compatible with the handler.
   */
4263cf0fa   Dmitry Torokhov   Input: make input...
1850
  int input_register_handler(struct input_handler *handler)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1851
1852
  {
  	struct input_dev *dev;
8006479c9   Dmitry Torokhov   Input: implement ...
1853
1854
1855
1856
1857
  	int retval;
  
  	retval = mutex_lock_interruptible(&input_mutex);
  	if (retval)
  		return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1858

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1859
  	INIT_LIST_HEAD(&handler->h_list);
4263cf0fa   Dmitry Torokhov   Input: make input...
1860
  	if (handler->fops != NULL) {
8006479c9   Dmitry Torokhov   Input: implement ...
1861
1862
1863
1864
  		if (input_table[handler->minor >> 5]) {
  			retval = -EBUSY;
  			goto out;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1865
  		input_table[handler->minor >> 5] = handler;
4263cf0fa   Dmitry Torokhov   Input: make input...
1866
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1867
1868
1869
1870
  
  	list_add_tail(&handler->node, &input_handler_list);
  
  	list_for_each_entry(dev, &input_dev_list, node)
5b2a08262   Dmitry Torokhov   Input: rework han...
1871
  		input_attach_handler(dev, handler);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1872

f96b434d3   Dmitry Torokhov   Input: rearrange ...
1873
  	input_wakeup_procfs_readers();
8006479c9   Dmitry Torokhov   Input: implement ...
1874
1875
1876
1877
  
   out:
  	mutex_unlock(&input_mutex);
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1878
  }
ca56fe07f   Dmitry Torokhov   Input: rearrange ...
1879
  EXPORT_SYMBOL(input_register_handler);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1880

8006479c9   Dmitry Torokhov   Input: implement ...
1881
1882
1883
1884
1885
1886
1887
  /**
   * input_unregister_handler - unregisters an input handler
   * @handler: handler to be unregistered
   *
   * This function disconnects a handler from its input devices and
   * removes it from lists of known handlers.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1888
1889
  void input_unregister_handler(struct input_handler *handler)
  {
5b2a08262   Dmitry Torokhov   Input: rework han...
1890
  	struct input_handle *handle, *next;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1891

8006479c9   Dmitry Torokhov   Input: implement ...
1892
  	mutex_lock(&input_mutex);
5b2a08262   Dmitry Torokhov   Input: rework han...
1893
  	list_for_each_entry_safe(handle, next, &handler->h_list, h_node)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1894
  		handler->disconnect(handle);
5b2a08262   Dmitry Torokhov   Input: rework han...
1895
  	WARN_ON(!list_empty(&handler->h_list));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1896
1897
1898
1899
1900
  
  	list_del_init(&handler->node);
  
  	if (handler->fops != NULL)
  		input_table[handler->minor >> 5] = NULL;
f96b434d3   Dmitry Torokhov   Input: rearrange ...
1901
  	input_wakeup_procfs_readers();
8006479c9   Dmitry Torokhov   Input: implement ...
1902
1903
  
  	mutex_unlock(&input_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1904
  }
ca56fe07f   Dmitry Torokhov   Input: rearrange ...
1905
  EXPORT_SYMBOL(input_unregister_handler);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1906

8006479c9   Dmitry Torokhov   Input: implement ...
1907
  /**
66d2a5952   Dmitry Torokhov   Input: keyboard -...
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
   * input_handler_for_each_handle - handle iterator
   * @handler: input handler to iterate
   * @data: data for the callback
   * @fn: function to be called for each handle
   *
   * Iterate over @bus's list of devices, and call @fn for each, passing
   * it @data and stop when @fn returns a non-zero value. The function is
   * using RCU to traverse the list and therefore may be usind in atonic
   * contexts. The @fn callback is invoked from RCU critical section and
   * thus must not sleep.
   */
  int input_handler_for_each_handle(struct input_handler *handler, void *data,
  				  int (*fn)(struct input_handle *, void *))
  {
  	struct input_handle *handle;
  	int retval = 0;
  
  	rcu_read_lock();
  
  	list_for_each_entry_rcu(handle, &handler->h_list, h_node) {
  		retval = fn(handle, data);
  		if (retval)
  			break;
  	}
  
  	rcu_read_unlock();
  
  	return retval;
  }
  EXPORT_SYMBOL(input_handler_for_each_handle);
  
  /**
8006479c9   Dmitry Torokhov   Input: implement ...
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
   * input_register_handle - register a new input handle
   * @handle: handle to register
   *
   * This function puts a new input handle onto device's
   * and handler's lists so that events can flow through
   * it once it is opened using input_open_device().
   *
   * This function is supposed to be called from handler's
   * connect() method.
   */
5b2a08262   Dmitry Torokhov   Input: rework han...
1950
1951
1952
  int input_register_handle(struct input_handle *handle)
  {
  	struct input_handler *handler = handle->handler;
8006479c9   Dmitry Torokhov   Input: implement ...
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
  	struct input_dev *dev = handle->dev;
  	int error;
  
  	/*
  	 * We take dev->mutex here to prevent race with
  	 * input_release_device().
  	 */
  	error = mutex_lock_interruptible(&dev->mutex);
  	if (error)
  		return error;
ef7995f4e   Dmitry Torokhov   Input: implement ...
1963
1964
1965
1966
1967
1968
1969
1970
1971
  
  	/*
  	 * Filters go to the head of the list, normal handlers
  	 * to the tail.
  	 */
  	if (handler->filter)
  		list_add_rcu(&handle->d_node, &dev->h_list);
  	else
  		list_add_tail_rcu(&handle->d_node, &dev->h_list);
8006479c9   Dmitry Torokhov   Input: implement ...
1972
  	mutex_unlock(&dev->mutex);
5b2a08262   Dmitry Torokhov   Input: rework han...
1973

8006479c9   Dmitry Torokhov   Input: implement ...
1974
1975
1976
1977
1978
1979
  	/*
  	 * Since we are supposed to be called from ->connect()
  	 * which is mutually exclusive with ->disconnect()
  	 * we can't be racing with input_unregister_handle()
  	 * and so separate lock is not needed here.
  	 */
66d2a5952   Dmitry Torokhov   Input: keyboard -...
1980
  	list_add_tail_rcu(&handle->h_node, &handler->h_list);
5b2a08262   Dmitry Torokhov   Input: rework han...
1981
1982
1983
1984
1985
1986
1987
  
  	if (handler->start)
  		handler->start(handle);
  
  	return 0;
  }
  EXPORT_SYMBOL(input_register_handle);
8006479c9   Dmitry Torokhov   Input: implement ...
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
  /**
   * input_unregister_handle - unregister an input handle
   * @handle: handle to unregister
   *
   * This function removes input handle from device's
   * and handler's lists.
   *
   * This function is supposed to be called from handler's
   * disconnect() method.
   */
5b2a08262   Dmitry Torokhov   Input: rework han...
1998
1999
  void input_unregister_handle(struct input_handle *handle)
  {
8006479c9   Dmitry Torokhov   Input: implement ...
2000
  	struct input_dev *dev = handle->dev;
66d2a5952   Dmitry Torokhov   Input: keyboard -...
2001
  	list_del_rcu(&handle->h_node);
8006479c9   Dmitry Torokhov   Input: implement ...
2002
2003
2004
2005
2006
2007
2008
  
  	/*
  	 * Take dev->mutex to prevent race with input_release_device().
  	 */
  	mutex_lock(&dev->mutex);
  	list_del_rcu(&handle->d_node);
  	mutex_unlock(&dev->mutex);
66d2a5952   Dmitry Torokhov   Input: keyboard -...
2009

82ba56c27   Dmitry Torokhov   Input: use full R...
2010
  	synchronize_rcu();
5b2a08262   Dmitry Torokhov   Input: rework han...
2011
2012
  }
  EXPORT_SYMBOL(input_unregister_handle);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2013
2014
  static int input_open_file(struct inode *inode, struct file *file)
  {
2edbf8537   Jonathan Corbet   Input: cdev lock_...
2015
  	struct input_handler *handler;
99ac48f54   Arjan van de Ven   [PATCH] mark f_op...
2016
  	const struct file_operations *old_fops, *new_fops = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2017
  	int err;
2f2177c8d   Arnd Bergmann   Input: remove BKL...
2018
2019
2020
  	err = mutex_lock_interruptible(&input_mutex);
  	if (err)
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2021
  	/* No load-on-demand here? */
2edbf8537   Jonathan Corbet   Input: cdev lock_...
2022
  	handler = input_table[iminor(inode) >> 5];
2f2177c8d   Arnd Bergmann   Input: remove BKL...
2023
2024
2025
2026
  	if (handler)
  		new_fops = fops_get(handler->fops);
  
  	mutex_unlock(&input_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2027
2028
2029
2030
2031
  
  	/*
  	 * That's _really_ odd. Usually NULL ->open means "nothing special",
  	 * not "no device". Oh, well...
  	 */
2f2177c8d   Arnd Bergmann   Input: remove BKL...
2032
  	if (!new_fops || !new_fops->open) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2033
  		fops_put(new_fops);
2edbf8537   Jonathan Corbet   Input: cdev lock_...
2034
2035
  		err = -ENODEV;
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2036
  	}
2f2177c8d   Arnd Bergmann   Input: remove BKL...
2037

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2038
2039
2040
2041
  	old_fops = file->f_op;
  	file->f_op = new_fops;
  
  	err = new_fops->open(inode, file);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2042
2043
2044
2045
2046
  	if (err) {
  		fops_put(file->f_op);
  		file->f_op = fops_get(old_fops);
  	}
  	fops_put(old_fops);
2edbf8537   Jonathan Corbet   Input: cdev lock_...
2047
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2048
2049
  	return err;
  }
2b8693c06   Arjan van de Ven   [PATCH] mark stru...
2050
  static const struct file_operations input_fops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2051
2052
  	.owner = THIS_MODULE,
  	.open = input_open_file,
6038f373a   Arnd Bergmann   llseek: automatic...
2053
  	.llseek = noop_llseek,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2054
  };
f96b434d3   Dmitry Torokhov   Input: rearrange ...
2055
  static int __init input_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2056
  {
f96b434d3   Dmitry Torokhov   Input: rearrange ...
2057
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2058

ea9f240bd   Greg Kroah-Hartman   [PATCH] INPUT: re...
2059
  	err = class_register(&input_class);
d19fbe8a7   Dmitry Torokhov   [PATCH] Input: pr...
2060
  	if (err) {
da0c49011   Joe Perches   Input: use pr_fmt...
2061
2062
  		pr_err("unable to register input_dev class
  ");
d19fbe8a7   Dmitry Torokhov   [PATCH] Input: pr...
2063
2064
  		return err;
  	}
f96b434d3   Dmitry Torokhov   Input: rearrange ...
2065
2066
  	err = input_proc_init();
  	if (err)
b0fdfebb2   Greg Kroah-Hartman   [PATCH] INPUT: re...
2067
  		goto fail1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2068

f96b434d3   Dmitry Torokhov   Input: rearrange ...
2069
2070
  	err = register_chrdev(INPUT_MAJOR, "input", &input_fops);
  	if (err) {
da0c49011   Joe Perches   Input: use pr_fmt...
2071
  		pr_err("unable to register char major %d", INPUT_MAJOR);
b0fdfebb2   Greg Kroah-Hartman   [PATCH] INPUT: re...
2072
  		goto fail2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2073
  	}
e334016fc   Luke Kosewski   Input: do not cor...
2074

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2075
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2076

b0fdfebb2   Greg Kroah-Hartman   [PATCH] INPUT: re...
2077
   fail2:	input_proc_exit();
ea9f240bd   Greg Kroah-Hartman   [PATCH] INPUT: re...
2078
   fail1:	class_unregister(&input_class);
f96b434d3   Dmitry Torokhov   Input: rearrange ...
2079
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2080
2081
2082
2083
  }
  
  static void __exit input_exit(void)
  {
f96b434d3   Dmitry Torokhov   Input: rearrange ...
2084
  	input_proc_exit();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2085
  	unregister_chrdev(INPUT_MAJOR, "input");
ea9f240bd   Greg Kroah-Hartman   [PATCH] INPUT: re...
2086
  	class_unregister(&input_class);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2087
2088
2089
2090
  }
  
  subsys_initcall(input_init);
  module_exit(input_exit);