aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/misc/uinput.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/misc/uinput.c')
-rw-r--r--drivers/input/misc/uinput.c181
1 files changed, 88 insertions, 93 deletions
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 98710997aaaa..d5c5b32045af 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -36,16 +36,6 @@
36#include <linux/miscdevice.h> 36#include <linux/miscdevice.h>
37#include <linux/uinput.h> 37#include <linux/uinput.h>
38 38
39static int uinput_dev_open(struct input_dev *dev)
40{
41 return 0;
42}
43
44static void uinput_dev_close(struct input_dev *dev)
45{
46
47}
48
49static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) 39static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
50{ 40{
51 struct uinput_device *udev; 41 struct uinput_device *udev;
@@ -63,22 +53,24 @@ static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned i
63 return 0; 53 return 0;
64} 54}
65 55
66static int uinput_request_alloc_id(struct input_dev *dev, struct uinput_request *request) 56static int uinput_request_alloc_id(struct uinput_device *udev, struct uinput_request *request)
67{ 57{
68 /* Atomically allocate an ID for the given request. Returns 0 on success. */ 58 /* Atomically allocate an ID for the given request. Returns 0 on success. */
69 struct uinput_device *udev = dev->private;
70 int id; 59 int id;
60 int err = -1;
61
62 spin_lock(&udev->requests_lock);
71 63
72 down(&udev->requests_sem); 64 for (id = 0; id < UINPUT_NUM_REQUESTS; id++)
73 for (id=0; id<UINPUT_NUM_REQUESTS; id++)
74 if (!udev->requests[id]) { 65 if (!udev->requests[id]) {
75 udev->requests[id] = request;
76 request->id = id; 66 request->id = id;
77 up(&udev->requests_sem); 67 udev->requests[id] = request;
78 return 0; 68 err = 0;
69 break;
79 } 70 }
80 up(&udev->requests_sem); 71
81 return -1; 72 spin_unlock(&udev->requests_lock);
73 return err;
82} 74}
83 75
84static struct uinput_request* uinput_request_find(struct uinput_device *udev, int id) 76static struct uinput_request* uinput_request_find(struct uinput_device *udev, int id)
@@ -86,70 +78,78 @@ static struct uinput_request* uinput_request_find(struct uinput_device *udev, in
86 /* Find an input request, by ID. Returns NULL if the ID isn't valid. */ 78 /* Find an input request, by ID. Returns NULL if the ID isn't valid. */
87 if (id >= UINPUT_NUM_REQUESTS || id < 0) 79 if (id >= UINPUT_NUM_REQUESTS || id < 0)
88 return NULL; 80 return NULL;
89 if (udev->requests[id]->completed)
90 return NULL;
91 return udev->requests[id]; 81 return udev->requests[id];
92} 82}
93 83
94static void uinput_request_init(struct input_dev *dev, struct uinput_request *request, int code) 84static inline int uinput_request_reserve_slot(struct uinput_device *udev, struct uinput_request *request)
95{ 85{
96 struct uinput_device *udev = dev->private; 86 /* Allocate slot. If none are available right away, wait. */
87 return wait_event_interruptible(udev->requests_waitq,
88 !uinput_request_alloc_id(udev, request));
89}
97 90
98 memset(request, 0, sizeof(struct uinput_request)); 91static void uinput_request_done(struct uinput_device *udev, struct uinput_request *request)
99 request->code = code; 92{
100 init_waitqueue_head(&request->waitq); 93 complete(&request->done);
101 94
102 /* Allocate an ID. If none are available right away, wait. */ 95 /* Mark slot as available */
103 request->retval = wait_event_interruptible(udev->requests_waitq, 96 udev->requests[request->id] = NULL;
104 !uinput_request_alloc_id(dev, request)); 97 wake_up_interruptible(&udev->requests_waitq);
105} 98}
106 99
107static void uinput_request_submit(struct input_dev *dev, struct uinput_request *request) 100static int uinput_request_submit(struct input_dev *dev, struct uinput_request *request)
108{ 101{
109 struct uinput_device *udev = dev->private;
110 int retval; 102 int retval;
111 103
112 /* Tell our userspace app about this new request by queueing an input event */ 104 /* Tell our userspace app about this new request by queueing an input event */
113 uinput_dev_event(dev, EV_UINPUT, request->code, request->id); 105 uinput_dev_event(dev, EV_UINPUT, request->code, request->id);
114 106
115 /* Wait for the request to complete */ 107 /* Wait for the request to complete */
116 retval = wait_event_interruptible(request->waitq, request->completed); 108 retval = wait_for_completion_interruptible(&request->done);
117 if (retval) 109 if (!retval)
118 request->retval = retval; 110 retval = request->retval;
119 111
120 /* Release this request's ID, let others know it's available */ 112 return retval;
121 udev->requests[request->id] = NULL;
122 wake_up_interruptible(&udev->requests_waitq);
123} 113}
124 114
125static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *effect) 115static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *effect)
126{ 116{
127 struct uinput_request request; 117 struct uinput_request request;
118 int retval;
128 119
129 if (!test_bit(EV_FF, dev->evbit)) 120 if (!test_bit(EV_FF, dev->evbit))
130 return -ENOSYS; 121 return -ENOSYS;
131 122
132 uinput_request_init(dev, &request, UI_FF_UPLOAD); 123 request.id = -1;
133 if (request.retval) 124 init_completion(&request.done);
134 return request.retval; 125 request.code = UI_FF_UPLOAD;
135 request.u.effect = effect; 126 request.u.effect = effect;
136 uinput_request_submit(dev, &request); 127
137 return request.retval; 128 retval = uinput_request_reserve_slot(dev->private, &request);
129 if (!retval)
130 retval = uinput_request_submit(dev, &request);
131
132 return retval;
138} 133}
139 134
140static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id) 135static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id)
141{ 136{
142 struct uinput_request request; 137 struct uinput_request request;
138 int retval;
143 139
144 if (!test_bit(EV_FF, dev->evbit)) 140 if (!test_bit(EV_FF, dev->evbit))
145 return -ENOSYS; 141 return -ENOSYS;
146 142
147 uinput_request_init(dev, &request, UI_FF_ERASE); 143 request.id = -1;
148 if (request.retval) 144 init_completion(&request.done);
149 return request.retval; 145 request.code = UI_FF_ERASE;
150 request.u.effect_id = effect_id; 146 request.u.effect_id = effect_id;
151 uinput_request_submit(dev, &request); 147
152 return request.retval; 148 retval = uinput_request_reserve_slot(dev->private, &request);
149 if (!retval)
150 retval = uinput_request_submit(dev, &request);
151
152 return retval;
153} 153}
154 154
155static int uinput_create_device(struct uinput_device *udev) 155static int uinput_create_device(struct uinput_device *udev)
@@ -159,32 +159,30 @@ static int uinput_create_device(struct uinput_device *udev)
159 return -EINVAL; 159 return -EINVAL;
160 } 160 }
161 161
162 udev->dev->open = uinput_dev_open;
163 udev->dev->close = uinput_dev_close;
164 udev->dev->event = uinput_dev_event; 162 udev->dev->event = uinput_dev_event;
165 udev->dev->upload_effect = uinput_dev_upload_effect; 163 udev->dev->upload_effect = uinput_dev_upload_effect;
166 udev->dev->erase_effect = uinput_dev_erase_effect; 164 udev->dev->erase_effect = uinput_dev_erase_effect;
167 udev->dev->private = udev; 165 udev->dev->private = udev;
168 166
169 init_waitqueue_head(&(udev->waitq)); 167 init_waitqueue_head(&udev->waitq);
170 168
171 input_register_device(udev->dev); 169 input_register_device(udev->dev);
172 170
173 set_bit(UIST_CREATED, &(udev->state)); 171 set_bit(UIST_CREATED, &udev->state);
174 172
175 return 0; 173 return 0;
176} 174}
177 175
178static int uinput_destroy_device(struct uinput_device *udev) 176static int uinput_destroy_device(struct uinput_device *udev)
179{ 177{
180 if (!test_bit(UIST_CREATED, &(udev->state))) { 178 if (!test_bit(UIST_CREATED, &udev->state)) {
181 printk(KERN_WARNING "%s: create the device first\n", UINPUT_NAME); 179 printk(KERN_WARNING "%s: create the device first\n", UINPUT_NAME);
182 return -EINVAL; 180 return -EINVAL;
183 } 181 }
184 182
185 input_unregister_device(udev->dev); 183 input_unregister_device(udev->dev);
186 184
187 clear_bit(UIST_CREATED, &(udev->state)); 185 clear_bit(UIST_CREATED, &udev->state);
188 186
189 return 0; 187 return 0;
190} 188}
@@ -198,7 +196,7 @@ static int uinput_open(struct inode *inode, struct file *file)
198 if (!newdev) 196 if (!newdev)
199 goto error; 197 goto error;
200 memset(newdev, 0, sizeof(struct uinput_device)); 198 memset(newdev, 0, sizeof(struct uinput_device));
201 init_MUTEX(&newdev->requests_sem); 199 spin_lock_init(&newdev->requests_lock);
202 init_waitqueue_head(&newdev->requests_waitq); 200 init_waitqueue_head(&newdev->requests_waitq);
203 201
204 newinput = kmalloc(sizeof(struct input_dev), GFP_KERNEL); 202 newinput = kmalloc(sizeof(struct input_dev), GFP_KERNEL);
@@ -253,15 +251,16 @@ static int uinput_alloc_device(struct file *file, const char __user *buffer, siz
253 struct uinput_user_dev *user_dev; 251 struct uinput_user_dev *user_dev;
254 struct input_dev *dev; 252 struct input_dev *dev;
255 struct uinput_device *udev; 253 struct uinput_device *udev;
256 int size, 254 char *name;
257 retval; 255 int size;
256 int retval;
258 257
259 retval = count; 258 retval = count;
260 259
261 udev = file->private_data; 260 udev = file->private_data;
262 dev = udev->dev; 261 dev = udev->dev;
263 262
264 user_dev = kmalloc(sizeof(*user_dev), GFP_KERNEL); 263 user_dev = kmalloc(sizeof(struct uinput_user_dev), GFP_KERNEL);
265 if (!user_dev) { 264 if (!user_dev) {
266 retval = -ENOMEM; 265 retval = -ENOMEM;
267 goto exit; 266 goto exit;
@@ -272,17 +271,17 @@ static int uinput_alloc_device(struct file *file, const char __user *buffer, siz
272 goto exit; 271 goto exit;
273 } 272 }
274 273
275 if (NULL != dev->name) 274 if (dev->name)
276 kfree(dev->name); 275 kfree(dev->name);
277 276
278 size = strnlen(user_dev->name, UINPUT_MAX_NAME_SIZE) + 1; 277 size = strnlen(user_dev->name, UINPUT_MAX_NAME_SIZE) + 1;
279 dev->name = kmalloc(size, GFP_KERNEL); 278 dev->name = name = kmalloc(size, GFP_KERNEL);
280 if (!dev->name) { 279 if (!name) {
281 retval = -ENOMEM; 280 retval = -ENOMEM;
282 goto exit; 281 goto exit;
283 } 282 }
283 strlcpy(name, user_dev->name, size);
284 284
285 strlcpy(dev->name, user_dev->name, size);
286 dev->id.bustype = user_dev->id.bustype; 285 dev->id.bustype = user_dev->id.bustype;
287 dev->id.vendor = user_dev->id.vendor; 286 dev->id.vendor = user_dev->id.vendor;
288 dev->id.product = user_dev->id.product; 287 dev->id.product = user_dev->id.product;
@@ -314,14 +313,13 @@ static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t
314{ 313{
315 struct uinput_device *udev = file->private_data; 314 struct uinput_device *udev = file->private_data;
316 315
317 if (test_bit(UIST_CREATED, &(udev->state))) { 316 if (test_bit(UIST_CREATED, &udev->state)) {
318 struct input_event ev; 317 struct input_event ev;
319 318
320 if (copy_from_user(&ev, buffer, sizeof(struct input_event))) 319 if (copy_from_user(&ev, buffer, sizeof(struct input_event)))
321 return -EFAULT; 320 return -EFAULT;
322 input_event(udev->dev, ev.type, ev.code, ev.value); 321 input_event(udev->dev, ev.type, ev.code, ev.value);
323 } 322 } else
324 else
325 count = uinput_alloc_device(file, buffer, count); 323 count = uinput_alloc_device(file, buffer, count);
326 324
327 return count; 325 return count;
@@ -332,26 +330,24 @@ static ssize_t uinput_read(struct file *file, char __user *buffer, size_t count,
332 struct uinput_device *udev = file->private_data; 330 struct uinput_device *udev = file->private_data;
333 int retval = 0; 331 int retval = 0;
334 332
335 if (!test_bit(UIST_CREATED, &(udev->state))) 333 if (!test_bit(UIST_CREATED, &udev->state))
336 return -ENODEV; 334 return -ENODEV;
337 335
338 if ((udev->head == udev->tail) && (file->f_flags & O_NONBLOCK)) 336 if (udev->head == udev->tail && (file->f_flags & O_NONBLOCK))
339 return -EAGAIN; 337 return -EAGAIN;
340 338
341 retval = wait_event_interruptible(udev->waitq, 339 retval = wait_event_interruptible(udev->waitq,
342 (udev->head != udev->tail) || 340 udev->head != udev->tail || !test_bit(UIST_CREATED, &udev->state));
343 !test_bit(UIST_CREATED, &(udev->state)));
344
345 if (retval) 341 if (retval)
346 return retval; 342 return retval;
347 343
348 if (!test_bit(UIST_CREATED, &(udev->state))) 344 if (!test_bit(UIST_CREATED, &udev->state))
349 return -ENODEV; 345 return -ENODEV;
350 346
351 while ((udev->head != udev->tail) && 347 while ((udev->head != udev->tail) &&
352 (retval + sizeof(struct input_event) <= count)) { 348 (retval + sizeof(struct input_event) <= count)) {
353 if (copy_to_user(buffer + retval, &(udev->buff[udev->tail]), 349 if (copy_to_user(buffer + retval, &udev->buff[udev->tail], sizeof(struct input_event)))
354 sizeof(struct input_event))) return -EFAULT; 350 return -EFAULT;
355 udev->tail = (udev->tail + 1) % UINPUT_BUFFER_SIZE; 351 udev->tail = (udev->tail + 1) % UINPUT_BUFFER_SIZE;
356 retval += sizeof(struct input_event); 352 retval += sizeof(struct input_event);
357 } 353 }
@@ -373,12 +369,12 @@ static unsigned int uinput_poll(struct file *file, poll_table *wait)
373 369
374static int uinput_burn_device(struct uinput_device *udev) 370static int uinput_burn_device(struct uinput_device *udev)
375{ 371{
376 if (test_bit(UIST_CREATED, &(udev->state))) 372 if (test_bit(UIST_CREATED, &udev->state))
377 uinput_destroy_device(udev); 373 uinput_destroy_device(udev);
378 374
379 if (NULL != udev->dev->name) 375 if (udev->dev->name)
380 kfree(udev->dev->name); 376 kfree(udev->dev->name);
381 if (NULL != udev->dev->phys) 377 if (udev->dev->phys)
382 kfree(udev->dev->phys); 378 kfree(udev->dev->phys);
383 379
384 kfree(udev->dev); 380 kfree(udev->dev);
@@ -389,7 +385,8 @@ static int uinput_burn_device(struct uinput_device *udev)
389 385
390static int uinput_close(struct inode *inode, struct file *file) 386static int uinput_close(struct inode *inode, struct file *file)
391{ 387{
392 return uinput_burn_device(file->private_data); 388 uinput_burn_device(file->private_data);
389 return 0;
393} 390}
394 391
395static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) 392static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
@@ -401,6 +398,7 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd
401 struct uinput_ff_erase ff_erase; 398 struct uinput_ff_erase ff_erase;
402 struct uinput_request *req; 399 struct uinput_request *req;
403 int length; 400 int length;
401 char *phys;
404 402
405 udev = file->private_data; 403 udev = file->private_data;
406 404
@@ -415,7 +413,7 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd
415 case UI_SET_SNDBIT: 413 case UI_SET_SNDBIT:
416 case UI_SET_FFBIT: 414 case UI_SET_FFBIT:
417 case UI_SET_PHYS: 415 case UI_SET_PHYS:
418 if (test_bit(UIST_CREATED, &(udev->state))) 416 if (test_bit(UIST_CREATED, &udev->state))
419 return -EINVAL; 417 return -EINVAL;
420 } 418 }
421 419
@@ -498,20 +496,19 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd
498 retval = -EFAULT; 496 retval = -EFAULT;
499 break; 497 break;
500 } 498 }
501 if (NULL != udev->dev->phys) 499 kfree(udev->dev->phys);
502 kfree(udev->dev->phys); 500 udev->dev->phys = phys = kmalloc(length, GFP_KERNEL);
503 udev->dev->phys = kmalloc(length, GFP_KERNEL); 501 if (!phys) {
504 if (!udev->dev->phys) {
505 retval = -ENOMEM; 502 retval = -ENOMEM;
506 break; 503 break;
507 } 504 }
508 if (copy_from_user(udev->dev->phys, p, length)) { 505 if (copy_from_user(phys, p, length)) {
509 retval = -EFAULT;
510 kfree(udev->dev->phys);
511 udev->dev->phys = NULL; 506 udev->dev->phys = NULL;
507 kfree(phys);
508 retval = -EFAULT;
512 break; 509 break;
513 } 510 }
514 udev->dev->phys[length-1] = '\0'; 511 phys[length - 1] = '\0';
515 break; 512 break;
516 513
517 case UI_BEGIN_FF_UPLOAD: 514 case UI_BEGIN_FF_UPLOAD:
@@ -520,7 +517,7 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd
520 break; 517 break;
521 } 518 }
522 req = uinput_request_find(udev, ff_up.request_id); 519 req = uinput_request_find(udev, ff_up.request_id);
523 if (!(req && req->code==UI_FF_UPLOAD && req->u.effect)) { 520 if (!(req && req->code == UI_FF_UPLOAD && req->u.effect)) {
524 retval = -EINVAL; 521 retval = -EINVAL;
525 break; 522 break;
526 } 523 }
@@ -538,7 +535,7 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd
538 break; 535 break;
539 } 536 }
540 req = uinput_request_find(udev, ff_erase.request_id); 537 req = uinput_request_find(udev, ff_erase.request_id);
541 if (!(req && req->code==UI_FF_ERASE)) { 538 if (!(req && req->code == UI_FF_ERASE)) {
542 retval = -EINVAL; 539 retval = -EINVAL;
543 break; 540 break;
544 } 541 }
@@ -556,14 +553,13 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd
556 break; 553 break;
557 } 554 }
558 req = uinput_request_find(udev, ff_up.request_id); 555 req = uinput_request_find(udev, ff_up.request_id);
559 if (!(req && req->code==UI_FF_UPLOAD && req->u.effect)) { 556 if (!(req && req->code == UI_FF_UPLOAD && req->u.effect)) {
560 retval = -EINVAL; 557 retval = -EINVAL;
561 break; 558 break;
562 } 559 }
563 req->retval = ff_up.retval; 560 req->retval = ff_up.retval;
564 memcpy(req->u.effect, &ff_up.effect, sizeof(struct ff_effect)); 561 memcpy(req->u.effect, &ff_up.effect, sizeof(struct ff_effect));
565 req->completed = 1; 562 uinput_request_done(udev, req);
566 wake_up_interruptible(&req->waitq);
567 break; 563 break;
568 564
569 case UI_END_FF_ERASE: 565 case UI_END_FF_ERASE:
@@ -572,13 +568,12 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd
572 break; 568 break;
573 } 569 }
574 req = uinput_request_find(udev, ff_erase.request_id); 570 req = uinput_request_find(udev, ff_erase.request_id);
575 if (!(req && req->code==UI_FF_ERASE)) { 571 if (!(req && req->code == UI_FF_ERASE)) {
576 retval = -EINVAL; 572 retval = -EINVAL;
577 break; 573 break;
578 } 574 }
579 req->retval = ff_erase.retval; 575 req->retval = ff_erase.retval;
580 req->completed = 1; 576 uinput_request_done(udev, req);
581 wake_up_interruptible(&req->waitq);
582 break; 577 break;
583 578
584 default: 579 default: