linux/drivers/input/input-compat.c
<<
>>
Prefs
   1/*
   2 * 32bit compatibility wrappers for the input subsystem.
   3 *
   4 * Very heavily based on evdev.c - Copyright (c) 1999-2002 Vojtech Pavlik
   5 *
   6 * This program is free software; you can redistribute it and/or modify it
   7 * under the terms of the GNU General Public License version 2 as published by
   8 * the Free Software Foundation.
   9 */
  10
  11#include <linux/export.h>
  12#include <asm/uaccess.h>
  13#include "input-compat.h"
  14
  15#ifdef CONFIG_COMPAT
  16
  17int input_event_from_user(const char __user *buffer,
  18                          struct input_event *event)
  19{
  20        if (INPUT_COMPAT_TEST && !COMPAT_USE_64BIT_TIME) {
  21                struct input_event_compat compat_event;
  22
  23                if (copy_from_user(&compat_event, buffer,
  24                                   sizeof(struct input_event_compat)))
  25                        return -EFAULT;
  26
  27                event->time.tv_sec = compat_event.time.tv_sec;
  28                event->time.tv_usec = compat_event.time.tv_usec;
  29                event->type = compat_event.type;
  30                event->code = compat_event.code;
  31                event->value = compat_event.value;
  32
  33        } else {
  34                if (copy_from_user(event, buffer, sizeof(struct input_event)))
  35                        return -EFAULT;
  36        }
  37
  38        return 0;
  39}
  40
  41int input_event_to_user(char __user *buffer,
  42                        const struct input_event *event)
  43{
  44        if (INPUT_COMPAT_TEST && !COMPAT_USE_64BIT_TIME) {
  45                struct input_event_compat compat_event;
  46
  47                compat_event.time.tv_sec = event->time.tv_sec;
  48                compat_event.time.tv_usec = event->time.tv_usec;
  49                compat_event.type = event->type;
  50                compat_event.code = event->code;
  51                compat_event.value = event->value;
  52
  53                if (copy_to_user(buffer, &compat_event,
  54                                 sizeof(struct input_event_compat)))
  55                        return -EFAULT;
  56
  57        } else {
  58                if (copy_to_user(buffer, event, sizeof(struct input_event)))
  59                        return -EFAULT;
  60        }
  61
  62        return 0;
  63}
  64
  65int input_ff_effect_from_user(const char __user *buffer, size_t size,
  66                              struct ff_effect *effect)
  67{
  68        if (INPUT_COMPAT_TEST) {
  69                struct ff_effect_compat *compat_effect;
  70
  71                if (size != sizeof(struct ff_effect_compat))
  72                        return -EINVAL;
  73
  74                /*
  75                 * It so happens that the pointer which needs to be changed
  76                 * is the last field in the structure, so we can retrieve the
  77                 * whole thing and replace just the pointer.
  78                 */
  79                compat_effect = (struct ff_effect_compat *)effect;
  80
  81                if (copy_from_user(compat_effect, buffer,
  82                                   sizeof(struct ff_effect_compat)))
  83                        return -EFAULT;
  84
  85                if (compat_effect->type == FF_PERIODIC &&
  86                    compat_effect->u.periodic.waveform == FF_CUSTOM)
  87                        effect->u.periodic.custom_data =
  88                                compat_ptr(compat_effect->u.periodic.custom_data);
  89        } else {
  90                if (size != sizeof(struct ff_effect))
  91                        return -EINVAL;
  92
  93                if (copy_from_user(effect, buffer, sizeof(struct ff_effect)))
  94                        return -EFAULT;
  95        }
  96
  97        return 0;
  98}
  99
 100#else
 101
 102int input_event_from_user(const char __user *buffer,
 103                         struct input_event *event)
 104{
 105        if (copy_from_user(event, buffer, sizeof(struct input_event)))
 106                return -EFAULT;
 107
 108        return 0;
 109}
 110
 111int input_event_to_user(char __user *buffer,
 112                        const struct input_event *event)
 113{
 114        if (copy_to_user(buffer, event, sizeof(struct input_event)))
 115                return -EFAULT;
 116
 117        return 0;
 118}
 119
 120int input_ff_effect_from_user(const char __user *buffer, size_t size,
 121                              struct ff_effect *effect)
 122{
 123        if (size != sizeof(struct ff_effect))
 124                return -EINVAL;
 125
 126        if (copy_from_user(effect, buffer, sizeof(struct ff_effect)))
 127                return -EFAULT;
 128
 129        return 0;
 130}
 131
 132#endif /* CONFIG_COMPAT */
 133
 134EXPORT_SYMBOL_GPL(input_event_from_user);
 135EXPORT_SYMBOL_GPL(input_event_to_user);
 136EXPORT_SYMBOL_GPL(input_ff_effect_from_user);
 137