diff options
Diffstat (limited to 'drivers/input/input.c')
-rw-r--r-- | drivers/input/input.c | 422 |
1 files changed, 262 insertions, 160 deletions
diff --git a/drivers/input/input.c b/drivers/input/input.c index f8af0945964e..a935abeffffc 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -18,9 +18,11 @@ | |||
18 | #include <linux/random.h> | 18 | #include <linux/random.h> |
19 | #include <linux/major.h> | 19 | #include <linux/major.h> |
20 | #include <linux/proc_fs.h> | 20 | #include <linux/proc_fs.h> |
21 | #include <linux/seq_file.h> | ||
21 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
22 | #include <linux/poll.h> | 23 | #include <linux/poll.h> |
23 | #include <linux/device.h> | 24 | #include <linux/device.h> |
25 | #include <linux/mutex.h> | ||
24 | 26 | ||
25 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); | 27 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); |
26 | MODULE_DESCRIPTION("Input core"); | 28 | MODULE_DESCRIPTION("Input core"); |
@@ -224,7 +226,7 @@ int input_open_device(struct input_handle *handle) | |||
224 | struct input_dev *dev = handle->dev; | 226 | struct input_dev *dev = handle->dev; |
225 | int err; | 227 | int err; |
226 | 228 | ||
227 | err = down_interruptible(&dev->sem); | 229 | err = mutex_lock_interruptible(&dev->mutex); |
228 | if (err) | 230 | if (err) |
229 | return err; | 231 | return err; |
230 | 232 | ||
@@ -236,7 +238,7 @@ int input_open_device(struct input_handle *handle) | |||
236 | if (err) | 238 | if (err) |
237 | handle->open--; | 239 | handle->open--; |
238 | 240 | ||
239 | up(&dev->sem); | 241 | mutex_unlock(&dev->mutex); |
240 | 242 | ||
241 | return err; | 243 | return err; |
242 | } | 244 | } |
@@ -255,13 +257,13 @@ void input_close_device(struct input_handle *handle) | |||
255 | 257 | ||
256 | input_release_device(handle); | 258 | input_release_device(handle); |
257 | 259 | ||
258 | down(&dev->sem); | 260 | mutex_lock(&dev->mutex); |
259 | 261 | ||
260 | if (!--dev->users && dev->close) | 262 | if (!--dev->users && dev->close) |
261 | dev->close(dev); | 263 | dev->close(dev); |
262 | handle->open--; | 264 | handle->open--; |
263 | 265 | ||
264 | up(&dev->sem); | 266 | mutex_unlock(&dev->mutex); |
265 | } | 267 | } |
266 | 268 | ||
267 | static void input_link_handle(struct input_handle *handle) | 269 | static void input_link_handle(struct input_handle *handle) |
@@ -315,21 +317,6 @@ static struct input_device_id *input_match_device(struct input_device_id *id, st | |||
315 | return NULL; | 317 | return NULL; |
316 | } | 318 | } |
317 | 319 | ||
318 | static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap, int max) | ||
319 | { | ||
320 | int i; | ||
321 | int len = 0; | ||
322 | |||
323 | for (i = NBITS(max) - 1; i > 0; i--) | ||
324 | if (bitmap[i]) | ||
325 | break; | ||
326 | |||
327 | for (; i >= 0; i--) | ||
328 | len += snprintf(buf + len, max(buf_size - len, 0), | ||
329 | "%lx%s", bitmap[i], i > 0 ? " " : ""); | ||
330 | return len; | ||
331 | } | ||
332 | |||
333 | #ifdef CONFIG_PROC_FS | 320 | #ifdef CONFIG_PROC_FS |
334 | 321 | ||
335 | static struct proc_dir_entry *proc_bus_input_dir; | 322 | static struct proc_dir_entry *proc_bus_input_dir; |
@@ -342,7 +329,7 @@ static inline void input_wakeup_procfs_readers(void) | |||
342 | wake_up(&input_devices_poll_wait); | 329 | wake_up(&input_devices_poll_wait); |
343 | } | 330 | } |
344 | 331 | ||
345 | static unsigned int input_devices_poll(struct file *file, poll_table *wait) | 332 | static unsigned int input_proc_devices_poll(struct file *file, poll_table *wait) |
346 | { | 333 | { |
347 | int state = input_devices_state; | 334 | int state = input_devices_state; |
348 | poll_wait(file, &input_devices_poll_wait, wait); | 335 | poll_wait(file, &input_devices_poll_wait, wait); |
@@ -351,115 +338,171 @@ static unsigned int input_devices_poll(struct file *file, poll_table *wait) | |||
351 | return 0; | 338 | return 0; |
352 | } | 339 | } |
353 | 340 | ||
354 | #define SPRINTF_BIT(ev, bm) \ | 341 | static struct list_head *list_get_nth_element(struct list_head *list, loff_t *pos) |
355 | do { \ | 342 | { |
356 | len += sprintf(buf + len, "B: %s=", #ev); \ | 343 | struct list_head *node; |
357 | len += input_print_bitmap(buf + len, INT_MAX, \ | 344 | loff_t i = 0; |
358 | dev->bm##bit, ev##_MAX); \ | ||
359 | len += sprintf(buf + len, "\n"); \ | ||
360 | } while (0) | ||
361 | 345 | ||
362 | #define TEST_AND_SPRINTF_BIT(ev, bm) \ | 346 | list_for_each(node, list) |
363 | do { \ | 347 | if (i++ == *pos) |
364 | if (test_bit(EV_##ev, dev->evbit)) \ | 348 | return node; |
365 | SPRINTF_BIT(ev, bm); \ | 349 | |
366 | } while (0) | 350 | return NULL; |
351 | } | ||
367 | 352 | ||
368 | static int input_devices_read(char *buf, char **start, off_t pos, int count, int *eof, void *data) | 353 | static struct list_head *list_get_next_element(struct list_head *list, struct list_head *element, loff_t *pos) |
369 | { | 354 | { |
370 | struct input_dev *dev; | 355 | if (element->next == list) |
371 | struct input_handle *handle; | 356 | return NULL; |
372 | const char *path; | 357 | |
358 | ++(*pos); | ||
359 | return element->next; | ||
360 | } | ||
361 | |||
362 | static void *input_devices_seq_start(struct seq_file *seq, loff_t *pos) | ||
363 | { | ||
364 | /* acquire lock here ... Yes, we do need locking, I knowi, I know... */ | ||
365 | |||
366 | return list_get_nth_element(&input_dev_list, pos); | ||
367 | } | ||
373 | 368 | ||
374 | off_t at = 0; | 369 | static void *input_devices_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
375 | int len, cnt = 0; | 370 | { |
371 | return list_get_next_element(&input_dev_list, v, pos); | ||
372 | } | ||
376 | 373 | ||
377 | list_for_each_entry(dev, &input_dev_list, node) { | 374 | static void input_devices_seq_stop(struct seq_file *seq, void *v) |
375 | { | ||
376 | /* release lock here */ | ||
377 | } | ||
378 | 378 | ||
379 | path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL); | 379 | static void input_seq_print_bitmap(struct seq_file *seq, const char *name, |
380 | unsigned long *bitmap, int max) | ||
381 | { | ||
382 | int i; | ||
380 | 383 | ||
381 | len = sprintf(buf, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n", | 384 | for (i = NBITS(max) - 1; i > 0; i--) |
382 | dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version); | 385 | if (bitmap[i]) |
386 | break; | ||
383 | 387 | ||
384 | len += sprintf(buf + len, "N: Name=\"%s\"\n", dev->name ? dev->name : ""); | 388 | seq_printf(seq, "B: %s=", name); |
385 | len += sprintf(buf + len, "P: Phys=%s\n", dev->phys ? dev->phys : ""); | 389 | for (; i >= 0; i--) |
386 | len += sprintf(buf + len, "S: Sysfs=%s\n", path ? path : ""); | 390 | seq_printf(seq, "%lx%s", bitmap[i], i > 0 ? " " : ""); |
387 | len += sprintf(buf + len, "H: Handlers="); | 391 | seq_putc(seq, '\n'); |
392 | } | ||
388 | 393 | ||
389 | list_for_each_entry(handle, &dev->h_list, d_node) | 394 | static int input_devices_seq_show(struct seq_file *seq, void *v) |
390 | len += sprintf(buf + len, "%s ", handle->name); | 395 | { |
391 | 396 | struct input_dev *dev = container_of(v, struct input_dev, node); | |
392 | len += sprintf(buf + len, "\n"); | 397 | const char *path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL); |
393 | 398 | struct input_handle *handle; | |
394 | SPRINTF_BIT(EV, ev); | ||
395 | TEST_AND_SPRINTF_BIT(KEY, key); | ||
396 | TEST_AND_SPRINTF_BIT(REL, rel); | ||
397 | TEST_AND_SPRINTF_BIT(ABS, abs); | ||
398 | TEST_AND_SPRINTF_BIT(MSC, msc); | ||
399 | TEST_AND_SPRINTF_BIT(LED, led); | ||
400 | TEST_AND_SPRINTF_BIT(SND, snd); | ||
401 | TEST_AND_SPRINTF_BIT(FF, ff); | ||
402 | TEST_AND_SPRINTF_BIT(SW, sw); | ||
403 | |||
404 | len += sprintf(buf + len, "\n"); | ||
405 | |||
406 | at += len; | ||
407 | |||
408 | if (at >= pos) { | ||
409 | if (!*start) { | ||
410 | *start = buf + (pos - (at - len)); | ||
411 | cnt = at - pos; | ||
412 | } else cnt += len; | ||
413 | buf += len; | ||
414 | if (cnt >= count) | ||
415 | break; | ||
416 | } | ||
417 | 399 | ||
418 | kfree(path); | 400 | seq_printf(seq, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n", |
419 | } | 401 | dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version); |
420 | 402 | ||
421 | if (&dev->node == &input_dev_list) | 403 | seq_printf(seq, "N: Name=\"%s\"\n", dev->name ? dev->name : ""); |
422 | *eof = 1; | 404 | seq_printf(seq, "P: Phys=%s\n", dev->phys ? dev->phys : ""); |
405 | seq_printf(seq, "S: Sysfs=%s\n", path ? path : ""); | ||
406 | seq_printf(seq, "H: Handlers="); | ||
423 | 407 | ||
424 | return (count > cnt) ? cnt : count; | 408 | list_for_each_entry(handle, &dev->h_list, d_node) |
409 | seq_printf(seq, "%s ", handle->name); | ||
410 | seq_putc(seq, '\n'); | ||
411 | |||
412 | input_seq_print_bitmap(seq, "EV", dev->evbit, EV_MAX); | ||
413 | if (test_bit(EV_KEY, dev->evbit)) | ||
414 | input_seq_print_bitmap(seq, "KEY", dev->keybit, KEY_MAX); | ||
415 | if (test_bit(EV_REL, dev->evbit)) | ||
416 | input_seq_print_bitmap(seq, "REL", dev->relbit, REL_MAX); | ||
417 | if (test_bit(EV_ABS, dev->evbit)) | ||
418 | input_seq_print_bitmap(seq, "ABS", dev->absbit, ABS_MAX); | ||
419 | if (test_bit(EV_MSC, dev->evbit)) | ||
420 | input_seq_print_bitmap(seq, "MSC", dev->mscbit, MSC_MAX); | ||
421 | if (test_bit(EV_LED, dev->evbit)) | ||
422 | input_seq_print_bitmap(seq, "LED", dev->ledbit, LED_MAX); | ||
423 | if (test_bit(EV_SND, dev->evbit)) | ||
424 | input_seq_print_bitmap(seq, "SND", dev->sndbit, SND_MAX); | ||
425 | if (test_bit(EV_FF, dev->evbit)) | ||
426 | input_seq_print_bitmap(seq, "FF", dev->ffbit, FF_MAX); | ||
427 | if (test_bit(EV_SW, dev->evbit)) | ||
428 | input_seq_print_bitmap(seq, "SW", dev->swbit, SW_MAX); | ||
429 | |||
430 | seq_putc(seq, '\n'); | ||
431 | |||
432 | kfree(path); | ||
433 | return 0; | ||
425 | } | 434 | } |
426 | 435 | ||
427 | static int input_handlers_read(char *buf, char **start, off_t pos, int count, int *eof, void *data) | 436 | static struct seq_operations input_devices_seq_ops = { |
437 | .start = input_devices_seq_start, | ||
438 | .next = input_devices_seq_next, | ||
439 | .stop = input_devices_seq_stop, | ||
440 | .show = input_devices_seq_show, | ||
441 | }; | ||
442 | |||
443 | static int input_proc_devices_open(struct inode *inode, struct file *file) | ||
428 | { | 444 | { |
429 | struct input_handler *handler; | 445 | return seq_open(file, &input_devices_seq_ops); |
446 | } | ||
430 | 447 | ||
431 | off_t at = 0; | 448 | static struct file_operations input_devices_fileops = { |
432 | int len = 0, cnt = 0; | 449 | .owner = THIS_MODULE, |
433 | int i = 0; | 450 | .open = input_proc_devices_open, |
451 | .poll = input_proc_devices_poll, | ||
452 | .read = seq_read, | ||
453 | .llseek = seq_lseek, | ||
454 | .release = seq_release, | ||
455 | }; | ||
434 | 456 | ||
435 | list_for_each_entry(handler, &input_handler_list, node) { | 457 | static void *input_handlers_seq_start(struct seq_file *seq, loff_t *pos) |
458 | { | ||
459 | /* acquire lock here ... Yes, we do need locking, I knowi, I know... */ | ||
460 | seq->private = (void *)(unsigned long)*pos; | ||
461 | return list_get_nth_element(&input_handler_list, pos); | ||
462 | } | ||
463 | |||
464 | static void *input_handlers_seq_next(struct seq_file *seq, void *v, loff_t *pos) | ||
465 | { | ||
466 | seq->private = (void *)(unsigned long)(*pos + 1); | ||
467 | return list_get_next_element(&input_handler_list, v, pos); | ||
468 | } | ||
436 | 469 | ||
437 | if (handler->fops) | 470 | static void input_handlers_seq_stop(struct seq_file *seq, void *v) |
438 | len = sprintf(buf, "N: Number=%d Name=%s Minor=%d\n", | 471 | { |
439 | i++, handler->name, handler->minor); | 472 | /* release lock here */ |
440 | else | 473 | } |
441 | len = sprintf(buf, "N: Number=%d Name=%s\n", | ||
442 | i++, handler->name); | ||
443 | 474 | ||
444 | at += len; | 475 | static int input_handlers_seq_show(struct seq_file *seq, void *v) |
476 | { | ||
477 | struct input_handler *handler = container_of(v, struct input_handler, node); | ||
445 | 478 | ||
446 | if (at >= pos) { | 479 | seq_printf(seq, "N: Number=%ld Name=%s", |
447 | if (!*start) { | 480 | (unsigned long)seq->private, handler->name); |
448 | *start = buf + (pos - (at - len)); | 481 | if (handler->fops) |
449 | cnt = at - pos; | 482 | seq_printf(seq, " Minor=%d", handler->minor); |
450 | } else cnt += len; | 483 | seq_putc(seq, '\n'); |
451 | buf += len; | ||
452 | if (cnt >= count) | ||
453 | break; | ||
454 | } | ||
455 | } | ||
456 | if (&handler->node == &input_handler_list) | ||
457 | *eof = 1; | ||
458 | 484 | ||
459 | return (count > cnt) ? cnt : count; | 485 | return 0; |
460 | } | 486 | } |
487 | static struct seq_operations input_handlers_seq_ops = { | ||
488 | .start = input_handlers_seq_start, | ||
489 | .next = input_handlers_seq_next, | ||
490 | .stop = input_handlers_seq_stop, | ||
491 | .show = input_handlers_seq_show, | ||
492 | }; | ||
461 | 493 | ||
462 | static struct file_operations input_fileops; | 494 | static int input_proc_handlers_open(struct inode *inode, struct file *file) |
495 | { | ||
496 | return seq_open(file, &input_handlers_seq_ops); | ||
497 | } | ||
498 | |||
499 | static struct file_operations input_handlers_fileops = { | ||
500 | .owner = THIS_MODULE, | ||
501 | .open = input_proc_handlers_open, | ||
502 | .read = seq_read, | ||
503 | .llseek = seq_lseek, | ||
504 | .release = seq_release, | ||
505 | }; | ||
463 | 506 | ||
464 | static int __init input_proc_init(void) | 507 | static int __init input_proc_init(void) |
465 | { | 508 | { |
@@ -471,20 +514,19 @@ static int __init input_proc_init(void) | |||
471 | 514 | ||
472 | proc_bus_input_dir->owner = THIS_MODULE; | 515 | proc_bus_input_dir->owner = THIS_MODULE; |
473 | 516 | ||
474 | entry = create_proc_read_entry("devices", 0, proc_bus_input_dir, input_devices_read, NULL); | 517 | entry = create_proc_entry("devices", 0, proc_bus_input_dir); |
475 | if (!entry) | 518 | if (!entry) |
476 | goto fail1; | 519 | goto fail1; |
477 | 520 | ||
478 | entry->owner = THIS_MODULE; | 521 | entry->owner = THIS_MODULE; |
479 | input_fileops = *entry->proc_fops; | 522 | entry->proc_fops = &input_devices_fileops; |
480 | input_fileops.poll = input_devices_poll; | ||
481 | entry->proc_fops = &input_fileops; | ||
482 | 523 | ||
483 | entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL); | 524 | entry = create_proc_entry("handlers", 0, proc_bus_input_dir); |
484 | if (!entry) | 525 | if (!entry) |
485 | goto fail2; | 526 | goto fail2; |
486 | 527 | ||
487 | entry->owner = THIS_MODULE; | 528 | entry->owner = THIS_MODULE; |
529 | entry->proc_fops = &input_handlers_fileops; | ||
488 | 530 | ||
489 | return 0; | 531 | return 0; |
490 | 532 | ||
@@ -512,13 +554,14 @@ static ssize_t input_dev_show_##name(struct class_device *dev, char *buf) \ | |||
512 | struct input_dev *input_dev = to_input_dev(dev); \ | 554 | struct input_dev *input_dev = to_input_dev(dev); \ |
513 | int retval; \ | 555 | int retval; \ |
514 | \ | 556 | \ |
515 | retval = down_interruptible(&input_dev->sem); \ | 557 | retval = mutex_lock_interruptible(&input_dev->mutex); \ |
516 | if (retval) \ | 558 | if (retval) \ |
517 | return retval; \ | 559 | return retval; \ |
518 | \ | 560 | \ |
519 | retval = sprintf(buf, "%s\n", input_dev->name ? input_dev->name : ""); \ | 561 | retval = scnprintf(buf, PAGE_SIZE, \ |
562 | "%s\n", input_dev->name ? input_dev->name : ""); \ | ||
520 | \ | 563 | \ |
521 | up(&input_dev->sem); \ | 564 | mutex_unlock(&input_dev->mutex); \ |
522 | \ | 565 | \ |
523 | return retval; \ | 566 | return retval; \ |
524 | } \ | 567 | } \ |
@@ -528,46 +571,51 @@ INPUT_DEV_STRING_ATTR_SHOW(name); | |||
528 | INPUT_DEV_STRING_ATTR_SHOW(phys); | 571 | INPUT_DEV_STRING_ATTR_SHOW(phys); |
529 | INPUT_DEV_STRING_ATTR_SHOW(uniq); | 572 | INPUT_DEV_STRING_ATTR_SHOW(uniq); |
530 | 573 | ||
531 | static int print_modalias_bits(char *buf, int size, char prefix, unsigned long *arr, | 574 | static int input_print_modalias_bits(char *buf, int size, |
532 | unsigned int min, unsigned int max) | 575 | char name, unsigned long *bm, |
576 | unsigned int min_bit, unsigned int max_bit) | ||
533 | { | 577 | { |
534 | int len, i; | 578 | int len = 0, i; |
535 | 579 | ||
536 | len = snprintf(buf, size, "%c", prefix); | 580 | len += snprintf(buf, max(size, 0), "%c", name); |
537 | for (i = min; i < max; i++) | 581 | for (i = min_bit; i < max_bit; i++) |
538 | if (arr[LONG(i)] & BIT(i)) | 582 | if (bm[LONG(i)] & BIT(i)) |
539 | len += snprintf(buf + len, size - len, "%X,", i); | 583 | len += snprintf(buf + len, max(size - len, 0), "%X,", i); |
540 | return len; | 584 | return len; |
541 | } | 585 | } |
542 | 586 | ||
543 | static int print_modalias(char *buf, int size, struct input_dev *id) | 587 | static int input_print_modalias(char *buf, int size, struct input_dev *id, |
588 | int add_cr) | ||
544 | { | 589 | { |
545 | int len; | 590 | int len; |
546 | 591 | ||
547 | len = snprintf(buf, size, "input:b%04Xv%04Xp%04Xe%04X-", | 592 | len = snprintf(buf, max(size, 0), |
548 | id->id.bustype, | 593 | "input:b%04Xv%04Xp%04Xe%04X-", |
549 | id->id.vendor, | 594 | id->id.bustype, id->id.vendor, |
550 | id->id.product, | 595 | id->id.product, id->id.version); |
551 | id->id.version); | 596 | |
552 | 597 | len += input_print_modalias_bits(buf + len, size - len, | |
553 | len += print_modalias_bits(buf + len, size - len, 'e', id->evbit, | 598 | 'e', id->evbit, 0, EV_MAX); |
554 | 0, EV_MAX); | 599 | len += input_print_modalias_bits(buf + len, size - len, |
555 | len += print_modalias_bits(buf + len, size - len, 'k', id->keybit, | 600 | 'k', id->keybit, KEY_MIN_INTERESTING, KEY_MAX); |
556 | KEY_MIN_INTERESTING, KEY_MAX); | 601 | len += input_print_modalias_bits(buf + len, size - len, |
557 | len += print_modalias_bits(buf + len, size - len, 'r', id->relbit, | 602 | 'r', id->relbit, 0, REL_MAX); |
558 | 0, REL_MAX); | 603 | len += input_print_modalias_bits(buf + len, size - len, |
559 | len += print_modalias_bits(buf + len, size - len, 'a', id->absbit, | 604 | 'a', id->absbit, 0, ABS_MAX); |
560 | 0, ABS_MAX); | 605 | len += input_print_modalias_bits(buf + len, size - len, |
561 | len += print_modalias_bits(buf + len, size - len, 'm', id->mscbit, | 606 | 'm', id->mscbit, 0, MSC_MAX); |
562 | 0, MSC_MAX); | 607 | len += input_print_modalias_bits(buf + len, size - len, |
563 | len += print_modalias_bits(buf + len, size - len, 'l', id->ledbit, | 608 | 'l', id->ledbit, 0, LED_MAX); |
564 | 0, LED_MAX); | 609 | len += input_print_modalias_bits(buf + len, size - len, |
565 | len += print_modalias_bits(buf + len, size - len, 's', id->sndbit, | 610 | 's', id->sndbit, 0, SND_MAX); |
566 | 0, SND_MAX); | 611 | len += input_print_modalias_bits(buf + len, size - len, |
567 | len += print_modalias_bits(buf + len, size - len, 'f', id->ffbit, | 612 | 'f', id->ffbit, 0, FF_MAX); |
568 | 0, FF_MAX); | 613 | len += input_print_modalias_bits(buf + len, size - len, |
569 | len += print_modalias_bits(buf + len, size - len, 'w', id->swbit, | 614 | 'w', id->swbit, 0, SW_MAX); |
570 | 0, SW_MAX); | 615 | |
616 | if (add_cr) | ||
617 | len += snprintf(buf + len, max(size - len, 0), "\n"); | ||
618 | |||
571 | return len; | 619 | return len; |
572 | } | 620 | } |
573 | 621 | ||
@@ -576,9 +624,9 @@ static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf) | |||
576 | struct input_dev *id = to_input_dev(dev); | 624 | struct input_dev *id = to_input_dev(dev); |
577 | ssize_t len; | 625 | ssize_t len; |
578 | 626 | ||
579 | len = print_modalias(buf, PAGE_SIZE, id); | 627 | len = input_print_modalias(buf, PAGE_SIZE, id, 1); |
580 | len += snprintf(buf + len, PAGE_SIZE-len, "\n"); | 628 | |
581 | return len; | 629 | return max_t(int, len, PAGE_SIZE); |
582 | } | 630 | } |
583 | static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL); | 631 | static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL); |
584 | 632 | ||
@@ -598,7 +646,7 @@ static struct attribute_group input_dev_attr_group = { | |||
598 | static ssize_t input_dev_show_id_##name(struct class_device *dev, char *buf) \ | 646 | static ssize_t input_dev_show_id_##name(struct class_device *dev, char *buf) \ |
599 | { \ | 647 | { \ |
600 | struct input_dev *input_dev = to_input_dev(dev); \ | 648 | struct input_dev *input_dev = to_input_dev(dev); \ |
601 | return sprintf(buf, "%04x\n", input_dev->id.name); \ | 649 | return scnprintf(buf, PAGE_SIZE, "%04x\n", input_dev->id.name); \ |
602 | } \ | 650 | } \ |
603 | static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL); | 651 | static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL); |
604 | 652 | ||
@@ -620,11 +668,33 @@ static struct attribute_group input_dev_id_attr_group = { | |||
620 | .attrs = input_dev_id_attrs, | 668 | .attrs = input_dev_id_attrs, |
621 | }; | 669 | }; |
622 | 670 | ||
671 | static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap, | ||
672 | int max, int add_cr) | ||
673 | { | ||
674 | int i; | ||
675 | int len = 0; | ||
676 | |||
677 | for (i = NBITS(max) - 1; i > 0; i--) | ||
678 | if (bitmap[i]) | ||
679 | break; | ||
680 | |||
681 | for (; i >= 0; i--) | ||
682 | len += snprintf(buf + len, max(buf_size - len, 0), | ||
683 | "%lx%s", bitmap[i], i > 0 ? " " : ""); | ||
684 | |||
685 | if (add_cr) | ||
686 | len += snprintf(buf + len, max(buf_size - len, 0), "\n"); | ||
687 | |||
688 | return len; | ||
689 | } | ||
690 | |||
623 | #define INPUT_DEV_CAP_ATTR(ev, bm) \ | 691 | #define INPUT_DEV_CAP_ATTR(ev, bm) \ |
624 | static ssize_t input_dev_show_cap_##bm(struct class_device *dev, char *buf) \ | 692 | static ssize_t input_dev_show_cap_##bm(struct class_device *dev, char *buf) \ |
625 | { \ | 693 | { \ |
626 | struct input_dev *input_dev = to_input_dev(dev); \ | 694 | struct input_dev *input_dev = to_input_dev(dev); \ |
627 | return input_print_bitmap(buf, PAGE_SIZE, input_dev->bm##bit, ev##_MAX);\ | 695 | int len = input_print_bitmap(buf, PAGE_SIZE, \ |
696 | input_dev->bm##bit, ev##_MAX, 1); \ | ||
697 | return min_t(int, len, PAGE_SIZE); \ | ||
628 | } \ | 698 | } \ |
629 | static CLASS_DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL); | 699 | static CLASS_DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL); |
630 | 700 | ||
@@ -669,8 +739,8 @@ static void input_dev_release(struct class_device *class_dev) | |||
669 | * device bitfields. | 739 | * device bitfields. |
670 | */ | 740 | */ |
671 | static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index, | 741 | static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index, |
672 | char *buffer, int buffer_size, int *cur_len, | 742 | char *buffer, int buffer_size, int *cur_len, |
673 | const char *name, unsigned long *bitmap, int max) | 743 | const char *name, unsigned long *bitmap, int max) |
674 | { | 744 | { |
675 | if (*cur_index >= num_envp - 1) | 745 | if (*cur_index >= num_envp - 1) |
676 | return -ENOMEM; | 746 | return -ENOMEM; |
@@ -678,12 +748,36 @@ static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index, | |||
678 | envp[*cur_index] = buffer + *cur_len; | 748 | envp[*cur_index] = buffer + *cur_len; |
679 | 749 | ||
680 | *cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0), name); | 750 | *cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0), name); |
681 | if (*cur_len > buffer_size) | 751 | if (*cur_len >= buffer_size) |
682 | return -ENOMEM; | 752 | return -ENOMEM; |
683 | 753 | ||
684 | *cur_len += input_print_bitmap(buffer + *cur_len, | 754 | *cur_len += input_print_bitmap(buffer + *cur_len, |
685 | max(buffer_size - *cur_len, 0), | 755 | max(buffer_size - *cur_len, 0), |
686 | bitmap, max) + 1; | 756 | bitmap, max, 0) + 1; |
757 | if (*cur_len > buffer_size) | ||
758 | return -ENOMEM; | ||
759 | |||
760 | (*cur_index)++; | ||
761 | return 0; | ||
762 | } | ||
763 | |||
764 | static int input_add_uevent_modalias_var(char **envp, int num_envp, int *cur_index, | ||
765 | char *buffer, int buffer_size, int *cur_len, | ||
766 | struct input_dev *dev) | ||
767 | { | ||
768 | if (*cur_index >= num_envp - 1) | ||
769 | return -ENOMEM; | ||
770 | |||
771 | envp[*cur_index] = buffer + *cur_len; | ||
772 | |||
773 | *cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0), | ||
774 | "MODALIAS="); | ||
775 | if (*cur_len >= buffer_size) | ||
776 | return -ENOMEM; | ||
777 | |||
778 | *cur_len += input_print_modalias(buffer + *cur_len, | ||
779 | max(buffer_size - *cur_len, 0), | ||
780 | dev, 0) + 1; | ||
687 | if (*cur_len > buffer_size) | 781 | if (*cur_len > buffer_size) |
688 | return -ENOMEM; | 782 | return -ENOMEM; |
689 | 783 | ||
@@ -693,7 +787,7 @@ static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index, | |||
693 | 787 | ||
694 | #define INPUT_ADD_HOTPLUG_VAR(fmt, val...) \ | 788 | #define INPUT_ADD_HOTPLUG_VAR(fmt, val...) \ |
695 | do { \ | 789 | do { \ |
696 | int err = add_uevent_var(envp, num_envp, &i, \ | 790 | int err = add_uevent_var(envp, num_envp, &i, \ |
697 | buffer, buffer_size, &len, \ | 791 | buffer, buffer_size, &len, \ |
698 | fmt, val); \ | 792 | fmt, val); \ |
699 | if (err) \ | 793 | if (err) \ |
@@ -709,6 +803,16 @@ static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index, | |||
709 | return err; \ | 803 | return err; \ |
710 | } while (0) | 804 | } while (0) |
711 | 805 | ||
806 | #define INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev) \ | ||
807 | do { \ | ||
808 | int err = input_add_uevent_modalias_var(envp, \ | ||
809 | num_envp, &i, \ | ||
810 | buffer, buffer_size, &len, \ | ||
811 | dev); \ | ||
812 | if (err) \ | ||
813 | return err; \ | ||
814 | } while (0) | ||
815 | |||
712 | static int input_dev_uevent(struct class_device *cdev, char **envp, | 816 | static int input_dev_uevent(struct class_device *cdev, char **envp, |
713 | int num_envp, char *buffer, int buffer_size) | 817 | int num_envp, char *buffer, int buffer_size) |
714 | { | 818 | { |
@@ -744,9 +848,7 @@ static int input_dev_uevent(struct class_device *cdev, char **envp, | |||
744 | if (test_bit(EV_SW, dev->evbit)) | 848 | if (test_bit(EV_SW, dev->evbit)) |
745 | INPUT_ADD_HOTPLUG_BM_VAR("SW=", dev->swbit, SW_MAX); | 849 | INPUT_ADD_HOTPLUG_BM_VAR("SW=", dev->swbit, SW_MAX); |
746 | 850 | ||
747 | envp[i++] = buffer + len; | 851 | INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev); |
748 | len += snprintf(buffer + len, buffer_size - len, "MODALIAS="); | ||
749 | len += print_modalias(buffer + len, buffer_size - len, dev) + 1; | ||
750 | 852 | ||
751 | envp[i] = NULL; | 853 | envp[i] = NULL; |
752 | return 0; | 854 | return 0; |
@@ -790,7 +892,7 @@ int input_register_device(struct input_dev *dev) | |||
790 | return -EINVAL; | 892 | return -EINVAL; |
791 | } | 893 | } |
792 | 894 | ||
793 | init_MUTEX(&dev->sem); | 895 | mutex_init(&dev->mutex); |
794 | set_bit(EV_SYN, dev->evbit); | 896 | set_bit(EV_SYN, dev->evbit); |
795 | 897 | ||
796 | /* | 898 | /* |