Commit 3a51f7c40437077ac4a463307e9a4ae6b78755a8

Authored by Dmitry Torokhov
1 parent e4f5c82a92

Input: evdev - consolidate compat and regular code

Compat and normal code mirror each other and are hard to maintain.
When EV_SW was added compat_ioctl case was missed. Here is my attempt
at consolidating the code.

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

Showing 1 changed file with 213 additions and 280 deletions Side-by-side Diff

drivers/input/evdev.c
... ... @@ -146,6 +146,7 @@
146 146 }
147 147  
148 148 #ifdef CONFIG_COMPAT
  149 +
149 150 struct input_event_compat {
150 151 struct compat_timeval time;
151 152 __u16 type;
152 153  
153 154  
154 155  
155 156  
156 157  
157 158  
158 159  
159 160  
160 161  
161 162  
162 163  
163 164  
164 165  
165 166  
166 167  
167 168  
168 169  
169 170  
170 171  
171 172  
172 173  
173 174  
174 175  
... ... @@ -165,98 +166,107 @@
165 166 # define COMPAT_TEST test_thread_flag(TIF_32BIT)
166 167 #endif
167 168  
168   -static ssize_t evdev_write_compat(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
  169 +static inline size_t evdev_event_size(void)
169 170 {
170   - struct evdev_list *list = file->private_data;
171   - struct input_event_compat event;
172   - int retval = 0;
  171 + return COMPAT_TEST ?
  172 + sizeof(struct input_event_compat) : sizeof(struct input_event);
  173 +}
173 174  
174   - while (retval < count) {
175   - if (copy_from_user(&event, buffer + retval, sizeof(struct input_event_compat)))
  175 +static int evdev_event_from_user(const char __user *buffer, struct input_event *event)
  176 +{
  177 + if (COMPAT_TEST) {
  178 + struct input_event_compat compat_event;
  179 +
  180 + if (copy_from_user(&compat_event, buffer, sizeof(struct input_event_compat)))
176 181 return -EFAULT;
177   - input_event(list->evdev->handle.dev, event.type, event.code, event.value);
178   - retval += sizeof(struct input_event_compat);
  182 +
  183 + event->time.tv_sec = compat_event.time.tv_sec;
  184 + event->time.tv_usec = compat_event.time.tv_usec;
  185 + event->type = compat_event.type;
  186 + event->code = compat_event.code;
  187 + event->value = compat_event.value;
  188 +
  189 + } else {
  190 + if (copy_from_user(event, buffer, sizeof(struct input_event)))
  191 + return -EFAULT;
179 192 }
180 193  
181   - return retval;
  194 + return 0;
182 195 }
183   -#endif
184 196  
185   -static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
  197 +static int evdev_event_to_user(char __user *buffer, const struct input_event *event)
186 198 {
187   - struct evdev_list *list = file->private_data;
188   - struct input_event event;
189   - int retval = 0;
  199 + if (COMPAT_TEST) {
  200 + struct input_event_compat compat_event;
190 201  
191   - if (!list->evdev->exist) return -ENODEV;
  202 + compat_event.time.tv_sec = event->time.tv_sec;
  203 + compat_event.time.tv_usec = event->time.tv_usec;
  204 + compat_event.type = event->type;
  205 + compat_event.code = event->code;
  206 + compat_event.value = event->value;
192 207  
193   -#ifdef CONFIG_COMPAT
194   - if (COMPAT_TEST)
195   - return evdev_write_compat(file, buffer, count, ppos);
196   -#endif
  208 + if (copy_to_user(buffer, &compat_event, sizeof(struct input_event_compat)))
  209 + return -EFAULT;
197 210  
198   - while (retval < count) {
199   -
200   - if (copy_from_user(&event, buffer + retval, sizeof(struct input_event)))
  211 + } else {
  212 + if (copy_to_user(buffer, event, sizeof(struct input_event)))
201 213 return -EFAULT;
202   - input_event(list->evdev->handle.dev, event.type, event.code, event.value);
203   - retval += sizeof(struct input_event);
204 214 }
205 215  
206   - return retval;
  216 + return 0;
207 217 }
208 218  
209   -#ifdef CONFIG_COMPAT
210   -static ssize_t evdev_read_compat(struct file * file, char __user * buffer, size_t count, loff_t *ppos)
  219 +#else
  220 +
  221 +static inline size_t evdev_event_size(void)
211 222 {
212   - struct evdev_list *list = file->private_data;
213   - int retval;
  223 + return sizeof(struct input_event);
  224 +}
214 225  
215   - if (count < sizeof(struct input_event_compat))
216   - return -EINVAL;
  226 +static int evdev_event_from_user(const char __user *buffer, struct input_event *event)
  227 +{
  228 + if (copy_from_user(event, buffer, sizeof(struct input_event)))
  229 + return -EFAULT;
217 230  
218   - if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK))
219   - return -EAGAIN;
  231 + return 0;
  232 +}
220 233  
221   - retval = wait_event_interruptible(list->evdev->wait,
222   - list->head != list->tail || (!list->evdev->exist));
  234 +static int evdev_event_to_user(char __user *buffer, const struct input_event *event)
  235 +{
  236 + if (copy_to_user(buffer, event, sizeof(struct input_event)))
  237 + return -EFAULT;
223 238  
224   - if (retval)
225   - return retval;
  239 + return 0;
  240 +}
226 241  
  242 +#endif /* CONFIG_COMPAT */
  243 +
  244 +static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
  245 +{
  246 + struct evdev_list *list = file->private_data;
  247 + struct input_event event;
  248 + int retval = 0;
  249 +
227 250 if (!list->evdev->exist)
228 251 return -ENODEV;
229 252  
230   - while (list->head != list->tail && retval + sizeof(struct input_event_compat) <= count) {
231   - struct input_event *event = (struct input_event *) list->buffer + list->tail;
232   - struct input_event_compat event_compat;
233   - event_compat.time.tv_sec = event->time.tv_sec;
234   - event_compat.time.tv_usec = event->time.tv_usec;
235   - event_compat.type = event->type;
236   - event_compat.code = event->code;
237   - event_compat.value = event->value;
  253 + while (retval < count) {
238 254  
239   - if (copy_to_user(buffer + retval, &event_compat,
240   - sizeof(struct input_event_compat))) return -EFAULT;
241   - list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1);
242   - retval += sizeof(struct input_event_compat);
  255 + if (evdev_event_from_user(buffer + retval, &event))
  256 + return -EFAULT;
  257 + input_event(list->evdev->handle.dev, event.type, event.code, event.value);
  258 + retval += evdev_event_size();
243 259 }
244 260  
245 261 return retval;
246 262 }
247   -#endif
248 263  
249 264 static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos)
250 265 {
251 266 struct evdev_list *list = file->private_data;
252 267 int retval;
253 268  
254   -#ifdef CONFIG_COMPAT
255   - if (COMPAT_TEST)
256   - return evdev_read_compat(file, buffer, count, ppos);
257   -#endif
258   -
259   - if (count < sizeof(struct input_event))
  269 + if (count < evdev_event_size())
260 270 return -EINVAL;
261 271  
262 272 if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK))
263 273  
... ... @@ -271,11 +281,15 @@
271 281 if (!list->evdev->exist)
272 282 return -ENODEV;
273 283  
274   - while (list->head != list->tail && retval + sizeof(struct input_event) <= count) {
275   - if (copy_to_user(buffer + retval, list->buffer + list->tail,
276   - sizeof(struct input_event))) return -EFAULT;
  284 + while (list->head != list->tail && retval + evdev_event_size() <= count) {
  285 +
  286 + struct input_event *event = (struct input_event *) list->buffer + list->tail;
  287 +
  288 + if (evdev_event_to_user(buffer + retval, event))
  289 + return -EFAULT;
  290 +
277 291 list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1);
278   - retval += sizeof(struct input_event);
  292 + retval += evdev_event_size();
279 293 }
280 294  
281 295 return retval;
282 296  
283 297  
284 298  
... ... @@ -290,17 +304,95 @@
290 304 (list->evdev->exist ? 0 : (POLLHUP | POLLERR));
291 305 }
292 306  
293   -static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  307 +#ifdef CONFIG_COMPAT
  308 +
  309 +#define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8)
  310 +#define NBITS_COMPAT(x) ((((x) - 1) / BITS_PER_LONG_COMPAT) + 1)
  311 +
  312 +#ifdef __BIG_ENDIAN
  313 +static int bits_to_user(unsigned long *bits, unsigned int maxbit,
  314 + unsigned int maxlen, void __user *p, int compat)
294 315 {
  316 + int len, i;
  317 +
  318 + if (compat) {
  319 + len = NBITS_COMPAT(maxbit) * sizeof(compat_long_t);
  320 + if (len < maxlen)
  321 + len = maxlen;
  322 +
  323 + for (i = 0; i < len / sizeof(compat_long_t); i++)
  324 + if (copy_to_user((compat_long_t __user *) p + i,
  325 + (compat_long_t *) bits +
  326 + i + 1 - ((i % 2) << 1),
  327 + sizeof(compat_long_t)))
  328 + return -EFAULT;
  329 + } else {
  330 + len = NBITS(maxbit) * sizeof(long);
  331 + if (len > maxlen)
  332 + len = maxlen;
  333 +
  334 + if (copy_to_user(p, bits, len))
  335 + return -EFAULT;
  336 + }
  337 +
  338 + return len;
  339 +}
  340 +#else
  341 +static int bits_to_user(unsigned long *bits, unsigned int maxbit,
  342 + unsigned int maxlen, void __user *p, int compat)
  343 +{
  344 + int len = compat ?
  345 + NBITS_COMPAT(maxbit) * sizeof(compat_long_t) :
  346 + NBITS(maxbit) * sizeof(long);
  347 +
  348 + if (len > maxlen)
  349 + len = maxlen;
  350 +
  351 + return copy_to_user(p, bits, len) ? -EFAULT : len;
  352 +}
  353 +#endif /* __BIG_ENDIAN */
  354 +
  355 +#else
  356 +
  357 +static int bits_to_user(unsigned long *bits, unsigned int maxbit,
  358 + unsigned int maxlen, void __user *p, int compat)
  359 +{
  360 + int len = NBITS(maxbit) * sizeof(long);
  361 +
  362 + if (len > maxlen)
  363 + len = maxlen;
  364 +
  365 + return copy_to_user(p, bits, len) ? -EFAULT : len;
  366 +}
  367 +
  368 +#endif /* CONFIG_COMPAT */
  369 +
  370 +static int str_to_user(const char *str, unsigned int maxlen, void __user *p)
  371 +{
  372 + int len;
  373 +
  374 + if (!str)
  375 + return -ENOENT;
  376 +
  377 + len = strlen(str) + 1;
  378 + if (len > maxlen)
  379 + len = maxlen;
  380 +
  381 + return copy_to_user(p, str, len) ? -EFAULT : len;
  382 +}
  383 +
  384 +static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
  385 + void __user *p, int compat_mode)
  386 +{
295 387 struct evdev_list *list = file->private_data;
296 388 struct evdev *evdev = list->evdev;
297 389 struct input_dev *dev = evdev->handle.dev;
298 390 struct input_absinfo abs;
299   - void __user *p = (void __user *)arg;
300   - int __user *ip = (int __user *)arg;
  391 + int __user *ip = (int __user *)p;
301 392 int i, t, u, v;
302 393  
303   - if (!evdev->exist) return -ENODEV;
  394 + if (!evdev->exist)
  395 + return -ENODEV;
304 396  
305 397 switch (cmd) {
306 398  
307 399  
308 400  
309 401  
310 402  
311 403  
... ... @@ -308,26 +400,39 @@
308 400 return put_user(EV_VERSION, ip);
309 401  
310 402 case EVIOCGID:
311   - return copy_to_user(p, &dev->id, sizeof(struct input_id)) ? -EFAULT : 0;
  403 + if (copy_to_user(p, &dev->id, sizeof(struct input_id)))
  404 + return -EFAULT;
312 405  
  406 + return 0;
  407 +
313 408 case EVIOCGKEYCODE:
314   - if (get_user(t, ip)) return -EFAULT;
315   - if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) return -EINVAL;
316   - if (put_user(INPUT_KEYCODE(dev, t), ip + 1)) return -EFAULT;
  409 + if (get_user(t, ip))
  410 + return -EFAULT;
  411 + if (t < 0 || t >= dev->keycodemax || !dev->keycodesize)
  412 + return -EINVAL;
  413 + if (put_user(INPUT_KEYCODE(dev, t), ip + 1))
  414 + return -EFAULT;
317 415 return 0;
318 416  
319 417 case EVIOCSKEYCODE:
320   - if (get_user(t, ip)) return -EFAULT;
321   - if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) return -EINVAL;
322   - if (get_user(v, ip + 1)) return -EFAULT;
323   - if (v < 0 || v > KEY_MAX) return -EINVAL;
324   - if (dev->keycodesize < sizeof(v) && (v >> (dev->keycodesize * 8))) return -EINVAL;
  418 + if (get_user(t, ip))
  419 + return -EFAULT;
  420 + if (t < 0 || t >= dev->keycodemax || !dev->keycodesize)
  421 + return -EINVAL;
  422 + if (get_user(v, ip + 1))
  423 + return -EFAULT;
  424 + if (v < 0 || v > KEY_MAX)
  425 + return -EINVAL;
  426 + if (dev->keycodesize < sizeof(v) && (v >> (dev->keycodesize * 8)))
  427 + return -EINVAL;
  428 +
325 429 u = SET_INPUT_KEYCODE(dev, t, v);
326 430 clear_bit(u, dev->keybit);
327 431 set_bit(v, dev->keybit);
328 432 for (i = 0; i < dev->keycodemax; i++)
329   - if (INPUT_KEYCODE(dev,i) == u)
  433 + if (INPUT_KEYCODE(dev, i) == u)
330 434 set_bit(u, dev->keybit);
  435 +
331 436 return 0;
332 437  
333 438 case EVIOCSFF:
334 439  
335 440  
336 441  
337 442  
... ... @@ -338,25 +443,25 @@
338 443 if (copy_from_user(&effect, p, sizeof(effect)))
339 444 return -EFAULT;
340 445 err = dev->upload_effect(dev, &effect);
341   - if (put_user(effect.id, &(((struct ff_effect __user *)arg)->id)))
  446 + if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
342 447 return -EFAULT;
343 448 return err;
344   - }
345   - else return -ENOSYS;
  449 + } else
  450 + return -ENOSYS;
346 451  
347 452 case EVIOCRMFF:
348   - if (dev->erase_effect) {
349   - return dev->erase_effect(dev, (int)arg);
350   - }
351   - else return -ENOSYS;
  453 + if (!dev->erase_effect)
  454 + return -ENOSYS;
352 455  
  456 + return dev->erase_effect(dev, (int)(unsigned long) p);
  457 +
353 458 case EVIOCGEFFECTS:
354 459 if (put_user(dev->ff_effects_max, ip))
355 460 return -EFAULT;
356 461 return 0;
357 462  
358 463 case EVIOCGRAB:
359   - if (arg) {
  464 + if (p) {
360 465 if (evdev->grab)
361 466 return -EBUSY;
362 467 if (input_grab_device(&evdev->handle))
363 468  
364 469  
365 470  
366 471  
367 472  
368 473  
369 474  
... ... @@ -395,62 +500,33 @@
395 500 case EV_SW: bits = dev->swbit; len = SW_MAX; break;
396 501 default: return -EINVAL;
397 502 }
398   - len = NBITS(len) * sizeof(long);
399   - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
400   - return copy_to_user(p, bits, len) ? -EFAULT : len;
  503 + return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode);
401 504 }
402 505  
403   - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) {
404   - int len;
405   - len = NBITS(KEY_MAX) * sizeof(long);
406   - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
407   - return copy_to_user(p, dev->key, len) ? -EFAULT : len;
408   - }
  506 + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0)))
  507 + return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd),
  508 + p, compat_mode);
409 509  
410   - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) {
411   - int len;
412   - len = NBITS(LED_MAX) * sizeof(long);
413   - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
414   - return copy_to_user(p, dev->led, len) ? -EFAULT : len;
415   - }
  510 + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0)))
  511 + return bits_to_user(dev->led, LED_MAX, _IOC_SIZE(cmd),
  512 + p, compat_mode);
416 513  
417   - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) {
418   - int len;
419   - len = NBITS(SND_MAX) * sizeof(long);
420   - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
421   - return copy_to_user(p, dev->snd, len) ? -EFAULT : len;
422   - }
  514 + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0)))
  515 + return bits_to_user(dev->snd, SND_MAX, _IOC_SIZE(cmd),
  516 + p, compat_mode);
423 517  
424   - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0))) {
425   - int len;
426   - len = NBITS(SW_MAX) * sizeof(long);
427   - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
428   - return copy_to_user(p, dev->sw, len) ? -EFAULT : len;
429   - }
  518 + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0)))
  519 + return bits_to_user(dev->sw, SW_MAX, _IOC_SIZE(cmd),
  520 + p, compat_mode);
430 521  
431   - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) {
432   - int len;
433   - if (!dev->name) return -ENOENT;
434   - len = strlen(dev->name) + 1;
435   - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
436   - return copy_to_user(p, dev->name, len) ? -EFAULT : len;
437   - }
  522 + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0)))
  523 + return str_to_user(dev->name, _IOC_SIZE(cmd), p);
438 524  
439   - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) {
440   - int len;
441   - if (!dev->phys) return -ENOENT;
442   - len = strlen(dev->phys) + 1;
443   - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
444   - return copy_to_user(p, dev->phys, len) ? -EFAULT : len;
445   - }
  525 + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0)))
  526 + return str_to_user(dev->phys, _IOC_SIZE(cmd), p);
446 527  
447   - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) {
448   - int len;
449   - if (!dev->uniq) return -ENOENT;
450   - len = strlen(dev->uniq) + 1;
451   - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
452   - return copy_to_user(p, dev->uniq, len) ? -EFAULT : len;
453   - }
  528 + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0)))
  529 + return str_to_user(dev->uniq, _IOC_SIZE(cmd), p);
454 530  
455 531 if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
456 532  
457 533  
458 534  
... ... @@ -492,158 +568,15 @@
492 568 return -EINVAL;
493 569 }
494 570  
495   -#ifdef CONFIG_COMPAT
  571 +static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  572 +{
  573 + return evdev_ioctl_handler(file, cmd, (void __user *)arg, 0);
  574 +}
496 575  
497   -#define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8)
498   -#define NBITS_COMPAT(x) ((((x)-1)/BITS_PER_LONG_COMPAT)+1)
499   -#define OFF_COMPAT(x) ((x)%BITS_PER_LONG_COMPAT)
500   -#define BIT_COMPAT(x) (1UL<<OFF_COMPAT(x))
501   -#define LONG_COMPAT(x) ((x)/BITS_PER_LONG_COMPAT)
502   -#define test_bit_compat(bit, array) ((array[LONG_COMPAT(bit)] >> OFF_COMPAT(bit)) & 1)
503   -
504   -#ifdef __BIG_ENDIAN
505   -#define bit_to_user(bit, max) \
506   -do { \
507   - int i; \
508   - int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \
509   - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \
510   - for (i = 0; i < len / sizeof(compat_long_t); i++) \
511   - if (copy_to_user((compat_long_t __user *) p + i, \
512   - (compat_long_t*) (bit) + i + 1 - ((i % 2) << 1), \
513   - sizeof(compat_long_t))) \
514   - return -EFAULT; \
515   - return len; \
516   -} while (0)
517   -#else
518   -#define bit_to_user(bit, max) \
519   -do { \
520   - int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \
521   - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \
522   - return copy_to_user(p, (bit), len) ? -EFAULT : len; \
523   -} while (0)
524   -#endif
525   -
  576 +#ifdef CONFIG_COMPAT
526 577 static long evdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
527 578 {
528   - struct evdev_list *list = file->private_data;
529   - struct evdev *evdev = list->evdev;
530   - struct input_dev *dev = evdev->handle.dev;
531   - struct input_absinfo abs;
532   - void __user *p = compat_ptr(arg);
533   -
534   - if (!evdev->exist) return -ENODEV;
535   -
536   - switch (cmd) {
537   -
538   - case EVIOCGVERSION:
539   - case EVIOCGID:
540   - case EVIOCGKEYCODE:
541   - case EVIOCSKEYCODE:
542   - case EVIOCSFF:
543   - case EVIOCRMFF:
544   - case EVIOCGEFFECTS:
545   - case EVIOCGRAB:
546   - return evdev_ioctl(file, cmd, (unsigned long) p);
547   -
548   - default:
549   -
550   - if (_IOC_TYPE(cmd) != 'E')
551   - return -EINVAL;
552   -
553   - if (_IOC_DIR(cmd) == _IOC_READ) {
554   -
555   - if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) {
556   - long *bits;
557   - int max;
558   -
559   - switch (_IOC_NR(cmd) & EV_MAX) {
560   - case 0: bits = dev->evbit; max = EV_MAX; break;
561   - case EV_KEY: bits = dev->keybit; max = KEY_MAX; break;
562   - case EV_REL: bits = dev->relbit; max = REL_MAX; break;
563   - case EV_ABS: bits = dev->absbit; max = ABS_MAX; break;
564   - case EV_MSC: bits = dev->mscbit; max = MSC_MAX; break;
565   - case EV_LED: bits = dev->ledbit; max = LED_MAX; break;
566   - case EV_SND: bits = dev->sndbit; max = SND_MAX; break;
567   - case EV_FF: bits = dev->ffbit; max = FF_MAX; break;
568   - case EV_SW: bits = dev->swbit; max = SW_MAX; break;
569   - default: return -EINVAL;
570   - }
571   - bit_to_user(bits, max);
572   - }
573   -
574   - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0)))
575   - bit_to_user(dev->key, KEY_MAX);
576   -
577   - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0)))
578   - bit_to_user(dev->led, LED_MAX);
579   -
580   - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0)))
581   - bit_to_user(dev->snd, SND_MAX);
582   -
583   - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0)))
584   - bit_to_user(dev->sw, SW_MAX);
585   -
586   - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) {
587   - int len;
588   - if (!dev->name) return -ENOENT;
589   - len = strlen(dev->name) + 1;
590   - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
591   - return copy_to_user(p, dev->name, len) ? -EFAULT : len;
592   - }
593   -
594   - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) {
595   - int len;
596   - if (!dev->phys) return -ENOENT;
597   - len = strlen(dev->phys) + 1;
598   - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
599   - return copy_to_user(p, dev->phys, len) ? -EFAULT : len;
600   - }
601   -
602   - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) {
603   - int len;
604   - if (!dev->uniq) return -ENOENT;
605   - len = strlen(dev->uniq) + 1;
606   - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
607   - return copy_to_user(p, dev->uniq, len) ? -EFAULT : len;
608   - }
609   -
610   - if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
611   -
612   - int t = _IOC_NR(cmd) & ABS_MAX;
613   -
614   - abs.value = dev->abs[t];
615   - abs.minimum = dev->absmin[t];
616   - abs.maximum = dev->absmax[t];
617   - abs.fuzz = dev->absfuzz[t];
618   - abs.flat = dev->absflat[t];
619   -
620   - if (copy_to_user(p, &abs, sizeof(struct input_absinfo)))
621   - return -EFAULT;
622   -
623   - return 0;
624   - }
625   - }
626   -
627   - if (_IOC_DIR(cmd) == _IOC_WRITE) {
628   -
629   - if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
630   -
631   - int t = _IOC_NR(cmd) & ABS_MAX;
632   -
633   - if (copy_from_user(&abs, p, sizeof(struct input_absinfo)))
634   - return -EFAULT;
635   -
636   - dev->abs[t] = abs.value;
637   - dev->absmin[t] = abs.minimum;
638   - dev->absmax[t] = abs.maximum;
639   - dev->absfuzz[t] = abs.fuzz;
640   - dev->absflat[t] = abs.flat;
641   -
642   - return 0;
643   - }
644   - }
645   - }
646   - return -EINVAL;
  579 + return evdev_ioctl_handler(file, cmd, compat_ptr(arg), 1);
647 580 }
648 581 #endif
649 582