Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/input/misc/uinput.c
15109 views
1
/*
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 <[email protected]>
21
*
22
* Changes/Revisions:
23
* 0.3 09/04/2006 (Anssi Hannula <[email protected]>)
24
* - updated ff support for the changes in kernel interface
25
* - added MODULE_VERSION
26
* 0.2 16/10/2004 (Micah Dowty <[email protected]>)
27
* - added force feedback support
28
* - added UI_SET_PHYS
29
* 0.1 20/06/2002
30
* - first public version
31
*/
32
#include <linux/poll.h>
33
#include <linux/sched.h>
34
#include <linux/slab.h>
35
#include <linux/module.h>
36
#include <linux/init.h>
37
#include <linux/fs.h>
38
#include <linux/miscdevice.h>
39
#include <linux/uinput.h>
40
#include <linux/input/mt.h>
41
#include "../input-compat.h"
42
43
static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
44
{
45
struct uinput_device *udev = input_get_drvdata(dev);
46
47
udev->buff[udev->head].type = type;
48
udev->buff[udev->head].code = code;
49
udev->buff[udev->head].value = value;
50
do_gettimeofday(&udev->buff[udev->head].time);
51
udev->head = (udev->head + 1) % UINPUT_BUFFER_SIZE;
52
53
wake_up_interruptible(&udev->waitq);
54
55
return 0;
56
}
57
58
/* Atomically allocate an ID for the given request. Returns 0 on success. */
59
static int uinput_request_alloc_id(struct uinput_device *udev, struct uinput_request *request)
60
{
61
int id;
62
int err = -1;
63
64
spin_lock(&udev->requests_lock);
65
66
for (id = 0; id < UINPUT_NUM_REQUESTS; id++) {
67
if (!udev->requests[id]) {
68
request->id = id;
69
udev->requests[id] = request;
70
err = 0;
71
break;
72
}
73
}
74
75
spin_unlock(&udev->requests_lock);
76
return err;
77
}
78
79
static struct uinput_request *uinput_request_find(struct uinput_device *udev, int id)
80
{
81
/* Find an input request, by ID. Returns NULL if the ID isn't valid. */
82
if (id >= UINPUT_NUM_REQUESTS || id < 0)
83
return NULL;
84
85
return udev->requests[id];
86
}
87
88
static inline int uinput_request_reserve_slot(struct uinput_device *udev, struct uinput_request *request)
89
{
90
/* Allocate slot. If none are available right away, wait. */
91
return wait_event_interruptible(udev->requests_waitq,
92
!uinput_request_alloc_id(udev, request));
93
}
94
95
static void uinput_request_done(struct uinput_device *udev, struct uinput_request *request)
96
{
97
/* Mark slot as available */
98
udev->requests[request->id] = NULL;
99
wake_up(&udev->requests_waitq);
100
101
complete(&request->done);
102
}
103
104
static int uinput_request_submit(struct uinput_device *udev, struct uinput_request *request)
105
{
106
int retval;
107
108
retval = uinput_request_reserve_slot(udev, request);
109
if (retval)
110
return retval;
111
112
retval = mutex_lock_interruptible(&udev->mutex);
113
if (retval)
114
return retval;
115
116
if (udev->state != UIST_CREATED) {
117
retval = -ENODEV;
118
goto out;
119
}
120
121
/* Tell our userspace app about this new request by queueing an input event */
122
uinput_dev_event(udev->dev, EV_UINPUT, request->code, request->id);
123
124
out:
125
mutex_unlock(&udev->mutex);
126
return retval;
127
}
128
129
/*
130
* Fail all ouitstanding requests so handlers don't wait for the userspace
131
* to finish processing them.
132
*/
133
static void uinput_flush_requests(struct uinput_device *udev)
134
{
135
struct uinput_request *request;
136
int i;
137
138
spin_lock(&udev->requests_lock);
139
140
for (i = 0; i < UINPUT_NUM_REQUESTS; i++) {
141
request = udev->requests[i];
142
if (request) {
143
request->retval = -ENODEV;
144
uinput_request_done(udev, request);
145
}
146
}
147
148
spin_unlock(&udev->requests_lock);
149
}
150
151
static void uinput_dev_set_gain(struct input_dev *dev, u16 gain)
152
{
153
uinput_dev_event(dev, EV_FF, FF_GAIN, gain);
154
}
155
156
static void uinput_dev_set_autocenter(struct input_dev *dev, u16 magnitude)
157
{
158
uinput_dev_event(dev, EV_FF, FF_AUTOCENTER, magnitude);
159
}
160
161
static int uinput_dev_playback(struct input_dev *dev, int effect_id, int value)
162
{
163
return uinput_dev_event(dev, EV_FF, effect_id, value);
164
}
165
166
static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old)
167
{
168
struct uinput_device *udev = input_get_drvdata(dev);
169
struct uinput_request request;
170
int retval;
171
172
/*
173
* uinput driver does not currently support periodic effects with
174
* custom waveform since it does not have a way to pass buffer of
175
* samples (custom_data) to userspace. If ever there is a device
176
* supporting custom waveforms we would need to define an additional
177
* ioctl (UI_UPLOAD_SAMPLES) but for now we just bail out.
178
*/
179
if (effect->type == FF_PERIODIC &&
180
effect->u.periodic.waveform == FF_CUSTOM)
181
return -EINVAL;
182
183
request.id = -1;
184
init_completion(&request.done);
185
request.code = UI_FF_UPLOAD;
186
request.u.upload.effect = effect;
187
request.u.upload.old = old;
188
189
retval = uinput_request_submit(udev, &request);
190
if (!retval) {
191
wait_for_completion(&request.done);
192
retval = request.retval;
193
}
194
195
return retval;
196
}
197
198
static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id)
199
{
200
struct uinput_device *udev = input_get_drvdata(dev);
201
struct uinput_request request;
202
int retval;
203
204
if (!test_bit(EV_FF, dev->evbit))
205
return -ENOSYS;
206
207
request.id = -1;
208
init_completion(&request.done);
209
request.code = UI_FF_ERASE;
210
request.u.effect_id = effect_id;
211
212
retval = uinput_request_submit(udev, &request);
213
if (!retval) {
214
wait_for_completion(&request.done);
215
retval = request.retval;
216
}
217
218
return retval;
219
}
220
221
static void uinput_destroy_device(struct uinput_device *udev)
222
{
223
const char *name, *phys;
224
struct input_dev *dev = udev->dev;
225
enum uinput_state old_state = udev->state;
226
227
udev->state = UIST_NEW_DEVICE;
228
229
if (dev) {
230
name = dev->name;
231
phys = dev->phys;
232
if (old_state == UIST_CREATED) {
233
uinput_flush_requests(udev);
234
input_unregister_device(dev);
235
} else {
236
input_free_device(dev);
237
}
238
kfree(name);
239
kfree(phys);
240
udev->dev = NULL;
241
}
242
}
243
244
static int uinput_create_device(struct uinput_device *udev)
245
{
246
struct input_dev *dev = udev->dev;
247
int error;
248
249
if (udev->state != UIST_SETUP_COMPLETE) {
250
printk(KERN_DEBUG "%s: write device info first\n", UINPUT_NAME);
251
return -EINVAL;
252
}
253
254
if (udev->ff_effects_max) {
255
error = input_ff_create(dev, udev->ff_effects_max);
256
if (error)
257
goto fail1;
258
259
dev->ff->upload = uinput_dev_upload_effect;
260
dev->ff->erase = uinput_dev_erase_effect;
261
dev->ff->playback = uinput_dev_playback;
262
dev->ff->set_gain = uinput_dev_set_gain;
263
dev->ff->set_autocenter = uinput_dev_set_autocenter;
264
}
265
266
error = input_register_device(udev->dev);
267
if (error)
268
goto fail2;
269
270
udev->state = UIST_CREATED;
271
272
return 0;
273
274
fail2: input_ff_destroy(dev);
275
fail1: uinput_destroy_device(udev);
276
return error;
277
}
278
279
static int uinput_open(struct inode *inode, struct file *file)
280
{
281
struct uinput_device *newdev;
282
283
newdev = kzalloc(sizeof(struct uinput_device), GFP_KERNEL);
284
if (!newdev)
285
return -ENOMEM;
286
287
mutex_init(&newdev->mutex);
288
spin_lock_init(&newdev->requests_lock);
289
init_waitqueue_head(&newdev->requests_waitq);
290
init_waitqueue_head(&newdev->waitq);
291
newdev->state = UIST_NEW_DEVICE;
292
293
file->private_data = newdev;
294
nonseekable_open(inode, file);
295
296
return 0;
297
}
298
299
static int uinput_validate_absbits(struct input_dev *dev)
300
{
301
unsigned int cnt;
302
int retval = 0;
303
304
for (cnt = 0; cnt < ABS_CNT; cnt++) {
305
int min, max;
306
if (!test_bit(cnt, dev->absbit))
307
continue;
308
309
min = input_abs_get_min(dev, cnt);
310
max = input_abs_get_max(dev, cnt);
311
312
if ((min != 0 || max != 0) && max <= min) {
313
printk(KERN_DEBUG
314
"%s: invalid abs[%02x] min:%d max:%d\n",
315
UINPUT_NAME, cnt,
316
input_abs_get_min(dev, cnt),
317
input_abs_get_max(dev, cnt));
318
retval = -EINVAL;
319
break;
320
}
321
322
if (input_abs_get_flat(dev, cnt) >
323
input_abs_get_max(dev, cnt) - input_abs_get_min(dev, cnt)) {
324
printk(KERN_DEBUG
325
"%s: abs_flat #%02x out of range: %d "
326
"(min:%d/max:%d)\n",
327
UINPUT_NAME, cnt,
328
input_abs_get_flat(dev, cnt),
329
input_abs_get_min(dev, cnt),
330
input_abs_get_max(dev, cnt));
331
retval = -EINVAL;
332
break;
333
}
334
}
335
return retval;
336
}
337
338
static int uinput_allocate_device(struct uinput_device *udev)
339
{
340
udev->dev = input_allocate_device();
341
if (!udev->dev)
342
return -ENOMEM;
343
344
udev->dev->event = uinput_dev_event;
345
input_set_drvdata(udev->dev, udev);
346
347
return 0;
348
}
349
350
static int uinput_setup_device(struct uinput_device *udev, const char __user *buffer, size_t count)
351
{
352
struct uinput_user_dev *user_dev;
353
struct input_dev *dev;
354
int i;
355
int retval;
356
357
if (count != sizeof(struct uinput_user_dev))
358
return -EINVAL;
359
360
if (!udev->dev) {
361
retval = uinput_allocate_device(udev);
362
if (retval)
363
return retval;
364
}
365
366
dev = udev->dev;
367
368
user_dev = memdup_user(buffer, sizeof(struct uinput_user_dev));
369
if (IS_ERR(user_dev))
370
return PTR_ERR(user_dev);
371
372
udev->ff_effects_max = user_dev->ff_effects_max;
373
374
/* Ensure name is filled in */
375
if (!user_dev->name[0]) {
376
retval = -EINVAL;
377
goto exit;
378
}
379
380
kfree(dev->name);
381
dev->name = kstrndup(user_dev->name, UINPUT_MAX_NAME_SIZE,
382
GFP_KERNEL);
383
if (!dev->name) {
384
retval = -ENOMEM;
385
goto exit;
386
}
387
388
dev->id.bustype = user_dev->id.bustype;
389
dev->id.vendor = user_dev->id.vendor;
390
dev->id.product = user_dev->id.product;
391
dev->id.version = user_dev->id.version;
392
393
for (i = 0; i < ABS_CNT; i++) {
394
input_abs_set_max(dev, i, user_dev->absmax[i]);
395
input_abs_set_min(dev, i, user_dev->absmin[i]);
396
input_abs_set_fuzz(dev, i, user_dev->absfuzz[i]);
397
input_abs_set_flat(dev, i, user_dev->absflat[i]);
398
}
399
400
/* check if absmin/absmax/absfuzz/absflat are filled as
401
* told in Documentation/input/input-programming.txt */
402
if (test_bit(EV_ABS, dev->evbit)) {
403
retval = uinput_validate_absbits(dev);
404
if (retval < 0)
405
goto exit;
406
if (test_bit(ABS_MT_SLOT, dev->absbit)) {
407
int nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1;
408
input_mt_init_slots(dev, nslot);
409
} else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
410
input_set_events_per_packet(dev, 60);
411
}
412
}
413
414
udev->state = UIST_SETUP_COMPLETE;
415
retval = count;
416
417
exit:
418
kfree(user_dev);
419
return retval;
420
}
421
422
static inline ssize_t uinput_inject_event(struct uinput_device *udev, const char __user *buffer, size_t count)
423
{
424
struct input_event ev;
425
426
if (count < input_event_size())
427
return -EINVAL;
428
429
if (input_event_from_user(buffer, &ev))
430
return -EFAULT;
431
432
input_event(udev->dev, ev.type, ev.code, ev.value);
433
434
return input_event_size();
435
}
436
437
static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
438
{
439
struct uinput_device *udev = file->private_data;
440
int retval;
441
442
retval = mutex_lock_interruptible(&udev->mutex);
443
if (retval)
444
return retval;
445
446
retval = udev->state == UIST_CREATED ?
447
uinput_inject_event(udev, buffer, count) :
448
uinput_setup_device(udev, buffer, count);
449
450
mutex_unlock(&udev->mutex);
451
452
return retval;
453
}
454
455
static ssize_t uinput_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
456
{
457
struct uinput_device *udev = file->private_data;
458
int retval = 0;
459
460
if (udev->state != UIST_CREATED)
461
return -ENODEV;
462
463
if (udev->head == udev->tail && (file->f_flags & O_NONBLOCK))
464
return -EAGAIN;
465
466
retval = wait_event_interruptible(udev->waitq,
467
udev->head != udev->tail || udev->state != UIST_CREATED);
468
if (retval)
469
return retval;
470
471
retval = mutex_lock_interruptible(&udev->mutex);
472
if (retval)
473
return retval;
474
475
if (udev->state != UIST_CREATED) {
476
retval = -ENODEV;
477
goto out;
478
}
479
480
while (udev->head != udev->tail && retval + input_event_size() <= count) {
481
if (input_event_to_user(buffer + retval, &udev->buff[udev->tail])) {
482
retval = -EFAULT;
483
goto out;
484
}
485
udev->tail = (udev->tail + 1) % UINPUT_BUFFER_SIZE;
486
retval += input_event_size();
487
}
488
489
out:
490
mutex_unlock(&udev->mutex);
491
492
return retval;
493
}
494
495
static unsigned int uinput_poll(struct file *file, poll_table *wait)
496
{
497
struct uinput_device *udev = file->private_data;
498
499
poll_wait(file, &udev->waitq, wait);
500
501
if (udev->head != udev->tail)
502
return POLLIN | POLLRDNORM;
503
504
return 0;
505
}
506
507
static int uinput_release(struct inode *inode, struct file *file)
508
{
509
struct uinput_device *udev = file->private_data;
510
511
uinput_destroy_device(udev);
512
kfree(udev);
513
514
return 0;
515
}
516
517
#ifdef CONFIG_COMPAT
518
struct uinput_ff_upload_compat {
519
int request_id;
520
int retval;
521
struct ff_effect_compat effect;
522
struct ff_effect_compat old;
523
};
524
525
static int uinput_ff_upload_to_user(char __user *buffer,
526
const struct uinput_ff_upload *ff_up)
527
{
528
if (INPUT_COMPAT_TEST) {
529
struct uinput_ff_upload_compat ff_up_compat;
530
531
ff_up_compat.request_id = ff_up->request_id;
532
ff_up_compat.retval = ff_up->retval;
533
/*
534
* It so happens that the pointer that gives us the trouble
535
* is the last field in the structure. Since we don't support
536
* custom waveforms in uinput anyway we can just copy the whole
537
* thing (to the compat size) and ignore the pointer.
538
*/
539
memcpy(&ff_up_compat.effect, &ff_up->effect,
540
sizeof(struct ff_effect_compat));
541
memcpy(&ff_up_compat.old, &ff_up->old,
542
sizeof(struct ff_effect_compat));
543
544
if (copy_to_user(buffer, &ff_up_compat,
545
sizeof(struct uinput_ff_upload_compat)))
546
return -EFAULT;
547
} else {
548
if (copy_to_user(buffer, ff_up,
549
sizeof(struct uinput_ff_upload)))
550
return -EFAULT;
551
}
552
553
return 0;
554
}
555
556
static int uinput_ff_upload_from_user(const char __user *buffer,
557
struct uinput_ff_upload *ff_up)
558
{
559
if (INPUT_COMPAT_TEST) {
560
struct uinput_ff_upload_compat ff_up_compat;
561
562
if (copy_from_user(&ff_up_compat, buffer,
563
sizeof(struct uinput_ff_upload_compat)))
564
return -EFAULT;
565
566
ff_up->request_id = ff_up_compat.request_id;
567
ff_up->retval = ff_up_compat.retval;
568
memcpy(&ff_up->effect, &ff_up_compat.effect,
569
sizeof(struct ff_effect_compat));
570
memcpy(&ff_up->old, &ff_up_compat.old,
571
sizeof(struct ff_effect_compat));
572
573
} else {
574
if (copy_from_user(ff_up, buffer,
575
sizeof(struct uinput_ff_upload)))
576
return -EFAULT;
577
}
578
579
return 0;
580
}
581
582
#else
583
584
static int uinput_ff_upload_to_user(char __user *buffer,
585
const struct uinput_ff_upload *ff_up)
586
{
587
if (copy_to_user(buffer, ff_up, sizeof(struct uinput_ff_upload)))
588
return -EFAULT;
589
590
return 0;
591
}
592
593
static int uinput_ff_upload_from_user(const char __user *buffer,
594
struct uinput_ff_upload *ff_up)
595
{
596
if (copy_from_user(ff_up, buffer, sizeof(struct uinput_ff_upload)))
597
return -EFAULT;
598
599
return 0;
600
}
601
602
#endif
603
604
#define uinput_set_bit(_arg, _bit, _max) \
605
({ \
606
int __ret = 0; \
607
if (udev->state == UIST_CREATED) \
608
__ret = -EINVAL; \
609
else if ((_arg) > (_max)) \
610
__ret = -EINVAL; \
611
else set_bit((_arg), udev->dev->_bit); \
612
__ret; \
613
})
614
615
static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
616
unsigned long arg, void __user *p)
617
{
618
int retval;
619
struct uinput_device *udev = file->private_data;
620
struct uinput_ff_upload ff_up;
621
struct uinput_ff_erase ff_erase;
622
struct uinput_request *req;
623
char *phys;
624
625
retval = mutex_lock_interruptible(&udev->mutex);
626
if (retval)
627
return retval;
628
629
if (!udev->dev) {
630
retval = uinput_allocate_device(udev);
631
if (retval)
632
goto out;
633
}
634
635
switch (cmd) {
636
case UI_DEV_CREATE:
637
retval = uinput_create_device(udev);
638
break;
639
640
case UI_DEV_DESTROY:
641
uinput_destroy_device(udev);
642
break;
643
644
case UI_SET_EVBIT:
645
retval = uinput_set_bit(arg, evbit, EV_MAX);
646
break;
647
648
case UI_SET_KEYBIT:
649
retval = uinput_set_bit(arg, keybit, KEY_MAX);
650
break;
651
652
case UI_SET_RELBIT:
653
retval = uinput_set_bit(arg, relbit, REL_MAX);
654
break;
655
656
case UI_SET_ABSBIT:
657
retval = uinput_set_bit(arg, absbit, ABS_MAX);
658
break;
659
660
case UI_SET_MSCBIT:
661
retval = uinput_set_bit(arg, mscbit, MSC_MAX);
662
break;
663
664
case UI_SET_LEDBIT:
665
retval = uinput_set_bit(arg, ledbit, LED_MAX);
666
break;
667
668
case UI_SET_SNDBIT:
669
retval = uinput_set_bit(arg, sndbit, SND_MAX);
670
break;
671
672
case UI_SET_FFBIT:
673
retval = uinput_set_bit(arg, ffbit, FF_MAX);
674
break;
675
676
case UI_SET_SWBIT:
677
retval = uinput_set_bit(arg, swbit, SW_MAX);
678
break;
679
680
case UI_SET_PROPBIT:
681
retval = uinput_set_bit(arg, propbit, INPUT_PROP_MAX);
682
break;
683
684
case UI_SET_PHYS:
685
if (udev->state == UIST_CREATED) {
686
retval = -EINVAL;
687
goto out;
688
}
689
690
phys = strndup_user(p, 1024);
691
if (IS_ERR(phys)) {
692
retval = PTR_ERR(phys);
693
goto out;
694
}
695
696
kfree(udev->dev->phys);
697
udev->dev->phys = phys;
698
break;
699
700
case UI_BEGIN_FF_UPLOAD:
701
retval = uinput_ff_upload_from_user(p, &ff_up);
702
if (retval)
703
break;
704
705
req = uinput_request_find(udev, ff_up.request_id);
706
if (!req || req->code != UI_FF_UPLOAD || !req->u.upload.effect) {
707
retval = -EINVAL;
708
break;
709
}
710
711
ff_up.retval = 0;
712
ff_up.effect = *req->u.upload.effect;
713
if (req->u.upload.old)
714
ff_up.old = *req->u.upload.old;
715
else
716
memset(&ff_up.old, 0, sizeof(struct ff_effect));
717
718
retval = uinput_ff_upload_to_user(p, &ff_up);
719
break;
720
721
case UI_BEGIN_FF_ERASE:
722
if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {
723
retval = -EFAULT;
724
break;
725
}
726
727
req = uinput_request_find(udev, ff_erase.request_id);
728
if (!req || req->code != UI_FF_ERASE) {
729
retval = -EINVAL;
730
break;
731
}
732
733
ff_erase.retval = 0;
734
ff_erase.effect_id = req->u.effect_id;
735
if (copy_to_user(p, &ff_erase, sizeof(ff_erase))) {
736
retval = -EFAULT;
737
break;
738
}
739
740
break;
741
742
case UI_END_FF_UPLOAD:
743
retval = uinput_ff_upload_from_user(p, &ff_up);
744
if (retval)
745
break;
746
747
req = uinput_request_find(udev, ff_up.request_id);
748
if (!req || req->code != UI_FF_UPLOAD ||
749
!req->u.upload.effect) {
750
retval = -EINVAL;
751
break;
752
}
753
754
req->retval = ff_up.retval;
755
uinput_request_done(udev, req);
756
break;
757
758
case UI_END_FF_ERASE:
759
if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {
760
retval = -EFAULT;
761
break;
762
}
763
764
req = uinput_request_find(udev, ff_erase.request_id);
765
if (!req || req->code != UI_FF_ERASE) {
766
retval = -EINVAL;
767
break;
768
}
769
770
req->retval = ff_erase.retval;
771
uinput_request_done(udev, req);
772
break;
773
774
default:
775
retval = -EINVAL;
776
}
777
778
out:
779
mutex_unlock(&udev->mutex);
780
return retval;
781
}
782
783
static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
784
{
785
return uinput_ioctl_handler(file, cmd, arg, (void __user *)arg);
786
}
787
788
#ifdef CONFIG_COMPAT
789
static long uinput_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
790
{
791
return uinput_ioctl_handler(file, cmd, arg, compat_ptr(arg));
792
}
793
#endif
794
795
static const struct file_operations uinput_fops = {
796
.owner = THIS_MODULE,
797
.open = uinput_open,
798
.release = uinput_release,
799
.read = uinput_read,
800
.write = uinput_write,
801
.poll = uinput_poll,
802
.unlocked_ioctl = uinput_ioctl,
803
#ifdef CONFIG_COMPAT
804
.compat_ioctl = uinput_compat_ioctl,
805
#endif
806
.llseek = no_llseek,
807
};
808
809
static struct miscdevice uinput_misc = {
810
.fops = &uinput_fops,
811
.minor = UINPUT_MINOR,
812
.name = UINPUT_NAME,
813
};
814
MODULE_ALIAS_MISCDEV(UINPUT_MINOR);
815
MODULE_ALIAS("devname:" UINPUT_NAME);
816
817
static int __init uinput_init(void)
818
{
819
return misc_register(&uinput_misc);
820
}
821
822
static void __exit uinput_exit(void)
823
{
824
misc_deregister(&uinput_misc);
825
}
826
827
MODULE_AUTHOR("Aristeu Sergio Rozanski Filho");
828
MODULE_DESCRIPTION("User level driver support for input subsystem");
829
MODULE_LICENSE("GPL");
830
MODULE_VERSION("0.3");
831
832
module_init(uinput_init);
833
module_exit(uinput_exit);
834
835
836