Input: sysrq - pass along lone Alt + SysRq

When user presses and releases Alt + SysRq without pressing any of the
hot keys re-inject the combination and pass it on to userspace instead
of suppressing it - maybe he or she wanted to take print screen
instead of invoking SysRq handler.

Also pass along release events for keys that have been pressed before
SysRq mode has been invoked so that keys do not appear to be "stuck".

Acked-by: Jason Wessel <jason.wessel@windriver.com>
Tested-by: Jason Wessel <jason.wessel@windriver.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

+127 -48
+127 -48
drivers/char/sysrq.c
··· 554 554 #ifdef CONFIG_INPUT 555 555 556 556 /* Simple translation table for the SysRq keys */ 557 - static const unsigned char sysrq_xlate[KEY_MAX + 1] = 557 + static const unsigned char sysrq_xlate[KEY_CNT] = 558 558 "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ 559 559 "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ 560 560 "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ ··· 563 563 "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ 564 564 "\r\000/"; /* 0x60 - 0x6f */ 565 565 566 - static bool sysrq_down; 567 - static int sysrq_alt_use; 568 - static int sysrq_alt; 569 - static DEFINE_SPINLOCK(sysrq_event_lock); 566 + struct sysrq_state { 567 + struct input_handle handle; 568 + struct work_struct reinject_work; 569 + unsigned long key_down[BITS_TO_LONGS(KEY_CNT)]; 570 + unsigned int alt; 571 + unsigned int alt_use; 572 + bool active; 573 + bool need_reinject; 574 + }; 570 575 571 - static bool sysrq_filter(struct input_handle *handle, unsigned int type, 572 - unsigned int code, int value) 576 + static void sysrq_reinject_alt_sysrq(struct work_struct *work) 573 577 { 578 + struct sysrq_state *sysrq = 579 + container_of(work, struct sysrq_state, reinject_work); 580 + struct input_handle *handle = &sysrq->handle; 581 + unsigned int alt_code = sysrq->alt_use; 582 + 583 + if (sysrq->need_reinject) { 584 + /* Simulate press and release of Alt + SysRq */ 585 + input_inject_event(handle, EV_KEY, alt_code, 1); 586 + input_inject_event(handle, EV_KEY, KEY_SYSRQ, 1); 587 + input_inject_event(handle, EV_SYN, SYN_REPORT, 1); 588 + 589 + input_inject_event(handle, EV_KEY, KEY_SYSRQ, 0); 590 + input_inject_event(handle, EV_KEY, alt_code, 0); 591 + input_inject_event(handle, EV_SYN, SYN_REPORT, 1); 592 + } 593 + } 594 + 595 + static bool sysrq_filter(struct input_handle *handle, 596 + unsigned int type, unsigned int code, int value) 597 + { 598 + struct sysrq_state *sysrq = handle->private; 599 + bool was_active = sysrq->active; 574 600 bool suppress; 575 601 576 - /* We are called with interrupts disabled, just take the lock */ 577 - spin_lock(&sysrq_event_lock); 602 + switch (type) { 578 603 579 - if (type != EV_KEY) 580 - goto out; 581 - 582 - switch (code) { 583 - 584 - case KEY_LEFTALT: 585 - case KEY_RIGHTALT: 586 - if (value) 587 - sysrq_alt = code; 588 - else { 589 - if (sysrq_down && code == sysrq_alt_use) 590 - sysrq_down = false; 591 - 592 - sysrq_alt = 0; 593 - } 604 + case EV_SYN: 605 + suppress = false; 594 606 break; 595 607 596 - case KEY_SYSRQ: 597 - if (value == 1 && sysrq_alt) { 598 - sysrq_down = true; 599 - sysrq_alt_use = sysrq_alt; 608 + case EV_KEY: 609 + switch (code) { 610 + 611 + case KEY_LEFTALT: 612 + case KEY_RIGHTALT: 613 + if (!value) { 614 + /* One of ALTs is being released */ 615 + if (sysrq->active && code == sysrq->alt_use) 616 + sysrq->active = false; 617 + 618 + sysrq->alt = KEY_RESERVED; 619 + 620 + } else if (value != 2) { 621 + sysrq->alt = code; 622 + sysrq->need_reinject = false; 623 + } 624 + break; 625 + 626 + case KEY_SYSRQ: 627 + if (value == 1 && sysrq->alt != KEY_RESERVED) { 628 + sysrq->active = true; 629 + sysrq->alt_use = sysrq->alt; 630 + /* 631 + * If nothing else will be pressed we'll need 632 + * to * re-inject Alt-SysRq keysroke. 633 + */ 634 + sysrq->need_reinject = true; 635 + } 636 + 637 + /* 638 + * Pretend that sysrq was never pressed at all. This 639 + * is needed to properly handle KGDB which will try 640 + * to release all keys after exiting debugger. If we 641 + * do not clear key bit it KGDB will end up sending 642 + * release events for Alt and SysRq, potentially 643 + * triggering print screen function. 644 + */ 645 + if (sysrq->active) 646 + clear_bit(KEY_SYSRQ, handle->dev->key); 647 + 648 + break; 649 + 650 + default: 651 + if (sysrq->active && value && value != 2) { 652 + sysrq->need_reinject = false; 653 + __handle_sysrq(sysrq_xlate[code], true); 654 + } 655 + break; 656 + } 657 + 658 + suppress = sysrq->active; 659 + 660 + if (!sysrq->active) { 661 + /* 662 + * If we are not suppressing key presses keep track of 663 + * keyboard state so we can release keys that have been 664 + * pressed before entering SysRq mode. 665 + */ 666 + if (value) 667 + set_bit(code, sysrq->key_down); 668 + else 669 + clear_bit(code, sysrq->key_down); 670 + 671 + if (was_active) 672 + schedule_work(&sysrq->reinject_work); 673 + 674 + } else if (value == 0 && 675 + test_and_clear_bit(code, sysrq->key_down)) { 676 + /* 677 + * Pass on release events for keys that was pressed before 678 + * entering SysRq mode. 679 + */ 680 + suppress = false; 600 681 } 601 682 break; 602 683 603 684 default: 604 - if (sysrq_down && value && value != 2) 605 - __handle_sysrq(sysrq_xlate[code], true); 685 + suppress = sysrq->active; 606 686 break; 607 687 } 608 - 609 - out: 610 - suppress = sysrq_down; 611 - spin_unlock(&sysrq_event_lock); 612 688 613 689 return suppress; 614 690 } ··· 693 617 struct input_dev *dev, 694 618 const struct input_device_id *id) 695 619 { 696 - struct input_handle *handle; 620 + struct sysrq_state *sysrq; 697 621 int error; 698 622 699 - sysrq_down = false; 700 - sysrq_alt = 0; 701 - 702 - handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); 703 - if (!handle) 623 + sysrq = kzalloc(sizeof(struct sysrq_state), GFP_KERNEL); 624 + if (!sysrq) 704 625 return -ENOMEM; 705 626 706 - handle->dev = dev; 707 - handle->handler = handler; 708 - handle->name = "sysrq"; 627 + INIT_WORK(&sysrq->reinject_work, sysrq_reinject_alt_sysrq); 709 628 710 - error = input_register_handle(handle); 629 + sysrq->handle.dev = dev; 630 + sysrq->handle.handler = handler; 631 + sysrq->handle.name = "sysrq"; 632 + sysrq->handle.private = sysrq; 633 + 634 + error = input_register_handle(&sysrq->handle); 711 635 if (error) { 712 636 pr_err("Failed to register input sysrq handler, error %d\n", 713 637 error); 714 638 goto err_free; 715 639 } 716 640 717 - error = input_open_device(handle); 641 + error = input_open_device(&sysrq->handle); 718 642 if (error) { 719 643 pr_err("Failed to open input device, error %d\n", error); 720 644 goto err_unregister; ··· 723 647 return 0; 724 648 725 649 err_unregister: 726 - input_unregister_handle(handle); 650 + input_unregister_handle(&sysrq->handle); 727 651 err_free: 728 - kfree(handle); 652 + kfree(sysrq); 729 653 return error; 730 654 } 731 655 732 656 static void sysrq_disconnect(struct input_handle *handle) 733 657 { 658 + struct sysrq_state *sysrq = handle->private; 659 + 734 660 input_close_device(handle); 661 + cancel_work_sync(&sysrq->reinject_work); 735 662 input_unregister_handle(handle); 736 - kfree(handle); 663 + kfree(sysrq); 737 664 } 738 665 739 666 /*