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 #ifdef CONFIG_INPUT 555 556 /* Simple translation table for the SysRq keys */ 557 - static const unsigned char sysrq_xlate[KEY_MAX + 1] = 558 "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ 559 "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ 560 "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ ··· 563 "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ 564 "\r\000/"; /* 0x60 - 0x6f */ 565 566 - static bool sysrq_down; 567 - static int sysrq_alt_use; 568 - static int sysrq_alt; 569 - static DEFINE_SPINLOCK(sysrq_event_lock); 570 571 - static bool sysrq_filter(struct input_handle *handle, unsigned int type, 572 - unsigned int code, int value) 573 { 574 bool suppress; 575 576 - /* We are called with interrupts disabled, just take the lock */ 577 - spin_lock(&sysrq_event_lock); 578 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 - } 594 break; 595 596 - case KEY_SYSRQ: 597 - if (value == 1 && sysrq_alt) { 598 - sysrq_down = true; 599 - sysrq_alt_use = sysrq_alt; 600 } 601 break; 602 603 default: 604 - if (sysrq_down && value && value != 2) 605 - __handle_sysrq(sysrq_xlate[code], true); 606 break; 607 } 608 - 609 - out: 610 - suppress = sysrq_down; 611 - spin_unlock(&sysrq_event_lock); 612 613 return suppress; 614 } ··· 693 struct input_dev *dev, 694 const struct input_device_id *id) 695 { 696 - struct input_handle *handle; 697 int error; 698 699 - sysrq_down = false; 700 - sysrq_alt = 0; 701 - 702 - handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); 703 - if (!handle) 704 return -ENOMEM; 705 706 - handle->dev = dev; 707 - handle->handler = handler; 708 - handle->name = "sysrq"; 709 710 - error = input_register_handle(handle); 711 if (error) { 712 pr_err("Failed to register input sysrq handler, error %d\n", 713 error); 714 goto err_free; 715 } 716 717 - error = input_open_device(handle); 718 if (error) { 719 pr_err("Failed to open input device, error %d\n", error); 720 goto err_unregister; ··· 723 return 0; 724 725 err_unregister: 726 - input_unregister_handle(handle); 727 err_free: 728 - kfree(handle); 729 return error; 730 } 731 732 static void sysrq_disconnect(struct input_handle *handle) 733 { 734 input_close_device(handle); 735 input_unregister_handle(handle); 736 - kfree(handle); 737 } 738 739 /*
··· 554 #ifdef CONFIG_INPUT 555 556 /* Simple translation table for the SysRq keys */ 557 + static const unsigned char sysrq_xlate[KEY_CNT] = 558 "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ 559 "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ 560 "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ ··· 563 "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ 564 "\r\000/"; /* 0x60 - 0x6f */ 565 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 + }; 575 576 + static void sysrq_reinject_alt_sysrq(struct work_struct *work) 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; 600 bool suppress; 601 602 + switch (type) { 603 604 + case EV_SYN: 605 + suppress = false; 606 break; 607 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; 681 } 682 break; 683 684 default: 685 + suppress = sysrq->active; 686 break; 687 } 688 689 return suppress; 690 } ··· 617 struct input_dev *dev, 618 const struct input_device_id *id) 619 { 620 + struct sysrq_state *sysrq; 621 int error; 622 623 + sysrq = kzalloc(sizeof(struct sysrq_state), GFP_KERNEL); 624 + if (!sysrq) 625 return -ENOMEM; 626 627 + INIT_WORK(&sysrq->reinject_work, sysrq_reinject_alt_sysrq); 628 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); 635 if (error) { 636 pr_err("Failed to register input sysrq handler, error %d\n", 637 error); 638 goto err_free; 639 } 640 641 + error = input_open_device(&sysrq->handle); 642 if (error) { 643 pr_err("Failed to open input device, error %d\n", error); 644 goto err_unregister; ··· 647 return 0; 648 649 err_unregister: 650 + input_unregister_handle(&sysrq->handle); 651 err_free: 652 + kfree(sysrq); 653 return error; 654 } 655 656 static void sysrq_disconnect(struct input_handle *handle) 657 { 658 + struct sysrq_state *sysrq = handle->private; 659 + 660 input_close_device(handle); 661 + cancel_work_sync(&sysrq->reinject_work); 662 input_unregister_handle(handle); 663 + kfree(sysrq); 664 } 665 666 /*