OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [input/] [uinput.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  User level driver support for input subsystem
3
 *
4
 * Heavily based on evdev.c by Vojtech Pavlik
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
 *
20
 * Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
21
 *
22
 * Changes/Revisions:
23
 *      0.1     20/06/2002
24
 *              - first public version
25
 */
26
 
27
#include <linux/poll.h>
28
#include <linux/slab.h>
29
#include <linux/module.h>
30
#include <linux/init.h>
31
#include <linux/input.h>
32
#include <linux/smp_lock.h>
33
#include <linux/fs.h>
34
#include <linux/miscdevice.h>
35
#include <linux/uinput.h>
36
 
37
static int uinput_dev_open(struct input_dev *dev)
38
{
39
        return 0;
40
}
41
 
42
static void uinput_dev_close(struct input_dev *dev)
43
{
44
}
45
 
46
static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
47
{
48
        struct uinput_device    *udev;
49
 
50
        udev = (struct uinput_device *)dev->private;
51
 
52
        udev->buff[udev->head].type = type;
53
        udev->buff[udev->head].code = code;
54
        udev->buff[udev->head].value = value;
55
        do_gettimeofday(&udev->buff[udev->head].time);
56
        udev->head = (udev->head + 1) % UINPUT_BUFFER_SIZE;
57
 
58
        wake_up_interruptible(&udev->waitq);
59
 
60
        return 0;
61
}
62
 
63
static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *effect)
64
{
65
        return 0;
66
}
67
 
68
static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id)
69
{
70
        return 0;
71
}
72
 
73
static int uinput_create_device(struct uinput_device *udev)
74
{
75
        if (!udev->dev->name) {
76
                printk(KERN_DEBUG "%s: write device info first\n", UINPUT_NAME);
77
                return -EINVAL;
78
        }
79
 
80
        udev->dev->open = uinput_dev_open;
81
        udev->dev->close = uinput_dev_close;
82
        udev->dev->event = uinput_dev_event;
83
        udev->dev->upload_effect = uinput_dev_upload_effect;
84
        udev->dev->erase_effect = uinput_dev_erase_effect;
85
        udev->dev->private = udev;
86
 
87
        init_waitqueue_head(&(udev->waitq));
88
 
89
        input_register_device(udev->dev);
90
 
91
        set_bit(UIST_CREATED, &(udev->state));
92
 
93
        return 0;
94
}
95
 
96
static int uinput_destroy_device(struct uinput_device *udev)
97
{
98
        if (!test_bit(UIST_CREATED, &(udev->state))) {
99
                printk(KERN_WARNING "%s: create the device first\n", UINPUT_NAME);
100
                return -EINVAL;
101
        }
102
 
103
        input_unregister_device(udev->dev);
104
 
105
        clear_bit(UIST_CREATED, &(udev->state));
106
 
107
        return 0;
108
}
109
 
110
static int uinput_open(struct inode *inode, struct file *file)
111
{
112
        struct uinput_device    *newdev;
113
        struct input_dev        *newinput;
114
 
115
        newdev = kmalloc(sizeof(struct uinput_device), GFP_KERNEL);
116
        if (!newdev)
117
                goto error;
118
        memset(newdev, 0, sizeof(struct uinput_device));
119
 
120
        newinput = kmalloc(sizeof(struct input_dev), GFP_KERNEL);
121
        if (!newinput)
122
                goto cleanup;
123
        memset(newinput, 0, sizeof(struct input_dev));
124
 
125
        newdev->dev = newinput;
126
 
127
        file->private_data = newdev;
128
 
129
        return 0;
130
cleanup:
131
        kfree(newdev);
132
error:
133
        return -ENOMEM;
134
}
135
 
136
static int uinput_validate_absbits(struct input_dev *dev)
137
{
138
        unsigned int cnt;
139
        int retval = 0;
140
 
141
        for (cnt = 0; cnt < ABS_MAX; cnt++) {
142
                if (!test_bit(cnt, dev->absbit))
143
                        continue;
144
 
145
                if (/*!dev->absmin[cnt] || !dev->absmax[cnt] || */
146
                    (dev->absmax[cnt] <= dev->absmin[cnt])) {
147
                        printk(KERN_DEBUG
148
                                "%s: invalid abs[%02x] min:%d max:%d\n",
149
                                UINPUT_NAME, cnt,
150
                                dev->absmin[cnt], dev->absmax[cnt]);
151
                        retval = -EINVAL;
152
                        break;
153
                }
154
 
155
                if ((dev->absflat[cnt] < dev->absmin[cnt]) ||
156
                    (dev->absflat[cnt] > dev->absmax[cnt])) {
157
                        printk(KERN_DEBUG
158
                                "%s: absflat[%02x] out of range: %d "
159
                                "(min:%d/max:%d)\n",
160
                                UINPUT_NAME, cnt, dev->absflat[cnt],
161
                                dev->absmin[cnt], dev->absmax[cnt]);
162
                        retval = -EINVAL;
163
                        break;
164
                }
165
        }
166
        return retval;
167
}
168
 
169
static int uinput_alloc_device(struct file *file, const char *buffer, size_t count)
170
{
171
        struct uinput_user_dev  *user_dev;
172
        struct input_dev        *dev;
173
        struct uinput_device    *udev;
174
        int                     size,
175
                                retval;
176
 
177
        retval = count;
178
 
179
        udev = (struct uinput_device *)file->private_data;
180
        dev = udev->dev;
181
 
182
        user_dev = kmalloc(sizeof(*user_dev), GFP_KERNEL);
183
        if (!user_dev) {
184
                retval = -ENOMEM;
185
                goto exit;
186
        }
187
 
188
        if (copy_from_user(user_dev, buffer, sizeof(struct uinput_user_dev))) {
189
                retval = -EFAULT;
190
                goto exit;
191
        }
192
 
193
        if (NULL != dev->name)
194
                kfree(dev->name);
195
 
196
        size = strnlen(user_dev->name, UINPUT_MAX_NAME_SIZE) + 1;
197
        dev->name = kmalloc(size, GFP_KERNEL);
198
        if (!dev->name) {
199
                retval = -ENOMEM;
200
                goto exit;
201
        }
202
 
203
        strncpy(dev->name, user_dev->name, size);
204
        dev->idbus      = user_dev->idbus;
205
        dev->idvendor   = user_dev->idvendor;
206
        dev->idproduct  = user_dev->idproduct;
207
        dev->idversion  = user_dev->idversion;
208
        dev->ff_effects_max = user_dev->ff_effects_max;
209
 
210
        size = sizeof(int) * (ABS_MAX + 1);
211
        memcpy(dev->absmax, user_dev->absmax, size);
212
        memcpy(dev->absmin, user_dev->absmin, size);
213
        memcpy(dev->absfuzz, user_dev->absfuzz, size);
214
        memcpy(dev->absflat, user_dev->absflat, size);
215
 
216
        /* check if absmin/absmax/absfuzz/absflat are filled as
217
         * told in Documentation/input/input-programming.txt */
218
        if (test_bit(EV_ABS, dev->evbit)) {
219
                retval = uinput_validate_absbits(dev);
220
                if (retval < 0)
221
                        kfree(dev->name);
222
        }
223
 
224
exit:
225
        kfree(user_dev);
226
        return retval;
227
}
228
 
229
static ssize_t uinput_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
230
{
231
        struct uinput_device    *udev = file->private_data;
232
 
233
        if (test_bit(UIST_CREATED, &(udev->state))) {
234
                struct input_event      ev;
235
 
236
                if (copy_from_user(&ev, buffer, sizeof(struct input_event)))
237
                        return -EFAULT;
238
                input_event(udev->dev, ev.type, ev.code, ev.value);
239
        }
240
        else
241
                count = uinput_alloc_device(file, buffer, count);
242
 
243
        return count;
244
}
245
 
246
static ssize_t uinput_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
247
{
248
        struct uinput_device *udev = file->private_data;
249
        int retval = 0;
250
 
251
        if (!test_bit(UIST_CREATED, &(udev->state)))
252
                return -ENODEV;
253
 
254
        if ((udev->head == udev->tail) && (file->f_flags & O_NONBLOCK))
255
                return -EAGAIN;
256
 
257
        retval = wait_event_interruptible(udev->waitq,
258
                        (udev->head != udev->tail) ||
259
                        !test_bit(UIST_CREATED, &(udev->state)));
260
 
261
        if (retval)
262
                return retval;
263
 
264
        if (!test_bit(UIST_CREATED, &(udev->state)))
265
                return -ENODEV;
266
 
267
        while ((udev->head != udev->tail) &&
268
            (retval + sizeof(struct input_event) <= count)) {
269
                if (copy_to_user(buffer + retval, &(udev->buff[udev->tail]),
270
                    sizeof(struct input_event))) return -EFAULT;
271
                udev->tail = (udev->tail + 1) % UINPUT_BUFFER_SIZE;
272
                retval += sizeof(struct input_event);
273
        }
274
 
275
        return retval;
276
}
277
 
278
static unsigned int uinput_poll(struct file *file, poll_table *wait)
279
{
280
        struct uinput_device *udev = file->private_data;
281
 
282
        poll_wait(file, &udev->waitq, wait);
283
 
284
        if (udev->head != udev->tail)
285
                return POLLIN | POLLRDNORM;
286
 
287
        return 0;
288
}
289
 
290
static int uinput_burn_device(struct uinput_device *udev)
291
{
292
        if (test_bit(UIST_CREATED, &(udev->state)))
293
                uinput_destroy_device(udev);
294
 
295
        kfree(udev->dev);
296
        kfree(udev);
297
 
298
        return 0;
299
}
300
 
301
static int uinput_close(struct inode *inode, struct file *file)
302
{
303
        return uinput_burn_device((struct uinput_device *)file->private_data);
304
}
305
 
306
static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
307
{
308
        int                     retval = 0;
309
        struct uinput_device    *udev;
310
 
311
        udev = (struct uinput_device *)file->private_data;
312
 
313
        /* device attributes can not be changed after the device is created */
314
        if (cmd >= UI_SET_EVBIT && test_bit(UIST_CREATED, &(udev->state)))
315
                return -EINVAL;
316
 
317
        switch (cmd) {
318
                case UI_DEV_CREATE:
319
                        retval = uinput_create_device(udev);
320
                        break;
321
 
322
                case UI_DEV_DESTROY:
323
                        retval = uinput_destroy_device(udev);
324
                        break;
325
 
326
                case UI_SET_EVBIT:
327
                        if (arg > EV_MAX) {
328
                                retval = -EINVAL;
329
                                break;
330
                        }
331
                        set_bit(arg, udev->dev->evbit);
332
                        break;
333
 
334
                case UI_SET_KEYBIT:
335
                        if (arg > KEY_MAX) {
336
                                retval = -EINVAL;
337
                                break;
338
                        }
339
                        set_bit(arg, udev->dev->keybit);
340
                        break;
341
 
342
                case UI_SET_RELBIT:
343
                        if (arg > REL_MAX) {
344
                                retval = -EINVAL;
345
                                break;
346
                        }
347
                        set_bit(arg, udev->dev->relbit);
348
                        break;
349
 
350
                case UI_SET_ABSBIT:
351
                        if (arg > ABS_MAX) {
352
                                retval = -EINVAL;
353
                                break;
354
                        }
355
                        set_bit(arg, udev->dev->absbit);
356
                        break;
357
 
358
                case UI_SET_MSCBIT:
359
                        if (arg > MSC_MAX) {
360
                                retval = -EINVAL;
361
                                break;
362
                        }
363
                        set_bit(arg, udev->dev->mscbit);
364
                        break;
365
 
366
                case UI_SET_LEDBIT:
367
                        if (arg > LED_MAX) {
368
                                retval = -EINVAL;
369
                                break;
370
                        }
371
                        set_bit(arg, udev->dev->ledbit);
372
                        break;
373
 
374
                case UI_SET_SNDBIT:
375
                        if (arg > SND_MAX) {
376
                                retval = -EINVAL;
377
                                break;
378
                        }
379
                        set_bit(arg, udev->dev->sndbit);
380
                        break;
381
 
382
                case UI_SET_FFBIT:
383
                        if (arg > FF_MAX) {
384
                                retval = -EINVAL;
385
                                break;
386
                        }
387
                        set_bit(arg, udev->dev->ffbit);
388
                        break;
389
 
390
                default:
391
                        retval = -EFAULT;
392
        }
393
        return retval;
394
}
395
 
396
struct file_operations uinput_fops = {
397
        owner:          THIS_MODULE,
398
        open:           uinput_open,
399
        release:        uinput_close,
400
        read:           uinput_read,
401
        write:          uinput_write,
402
        poll:           uinput_poll,
403
        ioctl:          uinput_ioctl,
404
};
405
 
406
static struct miscdevice uinput_misc = {
407
        fops:           &uinput_fops,
408
        minor:          UINPUT_MINOR,
409
        name:           UINPUT_NAME,
410
};
411
 
412
static int __init uinput_init(void)
413
{
414
        return misc_register(&uinput_misc);
415
}
416
 
417
static void __exit uinput_exit(void)
418
{
419
        misc_deregister(&uinput_misc);
420
}
421
 
422
MODULE_AUTHOR("Aristeu Sergio Rozanski Filho");
423
MODULE_DESCRIPTION("User level driver support for input subsystem");
424
MODULE_LICENSE("GPL");
425
 
426
module_init(uinput_init);
427
module_exit(uinput_exit);
428
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.