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 <asm/uaccess.h>
  12#include "input-compat.h"
  13
  14#ifdef CONFIG_COMPAT
  15
  16int input_event_from_user(const char __user *buffer,
  17                          struct input_event *event)
  18{
  19        if (INPUT_COMPAT_TEST) {
  20                struct input_event_compat compat_event;
  21
  22                if (copy_from_user(&compat_event, buffer,
  23                                   sizeof(struct input_event_compat)))
  24                        return -EFAULT;
  25
  26                event->time.tv_sec = compat_event.time.tv_sec;
  27                event->time.tv_usec = compat_event.time.tv_usec;
  28                event->type = compat_event.type;
  29                event->code = compat_event.code;
  30                event->value = compat_event.value;
  31
  32        } else {
  33                if (copy_from_user(event, buffer, sizeof(struct input_event)))
  34                        return -EFAULT;
  35        }
  36
  37        return 0;
  38}
  39
  40int input_event_to_user(char __user *buffer,
  41                        const struct input_event *event)
  42{
  43        if (INPUT_COMPAT_TEST) {
  44                struct input_event_compat compat_event;
  45
  46                compat_event.time.tv_sec = event->time.tv_sec;
  47                compat_event.time.tv_usec = event->time.tv_usec;
  48                compat_event.type = event->type;
  49                compat_event.code = event->code;
  50                compat_event.value = event->value;
  51
  52                if (copy_to_user(buffer, &compat_event,
  53                                 sizeof(struct input_event_compat)))
  54                        return -EFAULT;
  55
  56        } else {
  57                if (copy_to_user(buffer, event, sizeof(struct input_event)))
  58                        return -EFAULT;
  59        }
  60
  61        return 0;
  62}
  63
  64int input_ff_effect_from_user(const char __user *buffer, size_t size,
  65                              struct ff_effect *effect)
  66{
  67        if (INPUT_COMPAT_TEST) {
  68                struct ff_effect_compat *compat_effect;
  69
  70                if (size != sizeof(struct ff_effect_compat))
  71                        return -EINVAL;
  72
  73                /*
  74                 * It so happens that the pointer which needs to be changed
  75                 * is the last field in the structure, so we can retrieve the
  76                 * whole thing and replace just the pointer.
  77                 */
  78                compat_effect = (struct ff_effect_compat *)effect;
  79
  80                if (copy_from_user(compat_effect, buffer,
  81                                   sizeof(struct ff_effect_compat)))
  82                        return -EFAULT;
  83
  84                if (compat_effect->type == FF_PERIODIC &&
  85                    compat_effect->u.periodic.waveform == FF_CUSTOM)
  86                        effect->u.periodic.custom_data =
  87                                compat_ptr(compat_effect->u.periodic.custom_data);
  88        } else {
  89                if (size != sizeof(struct ff_effect))
  90                        return -EINVAL;
  91
  92                if (copy_from_user(effect, buffer, sizeof(struct ff_effect)))
  93                        return -EFAULT;
  94        }
  95
  96        return 0;
  97}
  98
  99#else
 100
 101int input_event_from_user(const char __user *buffer,
 102                         struct input_event *event)
 103{
 104        if (copy_from_user(event, buffer, sizeof(struct input_event)))
 105                return -EFAULT;
 106
 107        return 0;
 108}
 109
 110int input_event_to_user(char __user *buffer,
 111                        const struct input_event *event)
 112{
 113        if (copy_to_user(buffer, event, sizeof(struct input_event)))
 114                return -EFAULT;
 115
 116        return 0;
 117}
 118
 119int input_ff_effect_from_user(const char __user *buffer, size_t size,
 120                              struct ff_effect *effect)
 121{
 122        if (size != sizeof(struct ff_effect))
 123                return -EINVAL;
 124
 125        if (copy_from_user(effect, buffer, sizeof(struct ff_effect)))
 126                return -EFAULT;
 127
 128        return 0;
 129}
 130
 131#endif /* CONFIG_COMPAT */
 132
 133EXPORT_SYMBOL_GPL(input_event_from_user);
 134EXPORT_SYMBOL_GPL(input_event_to_user);
 135EXPORT_SYMBOL_GPL(input_ff_effect_from_user);
 136