Advertisement
Guest User

Untitled

a guest
Apr 29th, 2009
94
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.94 KB | None | 0 0
  1. /* sysrq-visual.c
  2.  *
  3.  * Kernel module adding a magic SysRq handler that generates a visual response (flash the keyboard leds once),
  4.  * so you know that magic SysRq is still there.
  5.  *
  6.  * I'm a kernel hacking newb so most of this was copied from examples and documentation.
  7.  *
  8.  * assaf d0t berg @t gmail dot c0m
  9.  */
  10.  
  11. #include <linux/module.h>
  12. #include <linux/kernel.h>
  13. #include <linux/sysrq.h>
  14. #include <linux/kbd_kern.h>
  15. #include <linux/init.h>
  16. #include <linux/tty.h>      /* For fg_console, MAX_NR_CONSOLES */
  17. #include <linux/kd.h>       /* For KDSETLED */
  18. #include <linux/vt.h>
  19. #include <linux/vt_kern.h>
  20. #include <linux/console_struct.h>   /* For vc_cons */
  21. #include <linux/workqueue.h>
  22.  
  23. #define BLINK_DELAY   HZ/5
  24.  
  25. #define BEEP_ON ((125 << 16) + 1591)
  26. #define BEEP_OFF 0
  27.  
  28. static void my_work_func(struct work_struct *);
  29. DECLARE_DELAYED_WORK(my_work, my_work_func);
  30.  
  31. struct tty_driver *my_driver;
  32. static long last_start_jiffies = 0;
  33.  
  34. /**
  35.  * entry point for handling a magic SysRq
  36.  */
  37. void visual_handler (int key, struct tty_struct *tty);
  38.  
  39. /**
  40.  * The SysRq op structure for our handler
  41.  */
  42. struct sysrq_key_op visual_op = {
  43.         handler: visual_handler,
  44.         help_msg: "Visual",
  45.         action_msg: "Blinking..."
  46. };
  47.  
  48. /**
  49.  * Set the led state using the given parameter
  50.  */
  51. static void my_flip_leds(void) {
  52.     char ledstatus = 0;
  53.     (my_driver->ops->ioctl) (vc_cons[fg_console].d->vc_tty, NULL, KDGETLED,
  54.                 (unsigned long) &ledstatus);
  55.  
  56.     ledstatus = (~ledstatus) & 7;
  57.  
  58.     (my_driver->ops->ioctl) (vc_cons[fg_console].d->vc_tty, NULL, KDSETLED,
  59.                 ledstatus);
  60. }
  61.  
  62.  
  63. static void my_set_beep(int tone) {
  64.     (my_driver->ops->ioctl) (vc_cons[fg_console].d->vc_tty, NULL, KDMKTONE,
  65.                 tone);
  66. }
  67.  
  68. /**
  69.  * function to to turn on the leds and reset the leds after a small delay
  70.  */
  71. static void my_work_func(struct work_struct *ws)
  72. {
  73.     int ret;
  74.  
  75.     /* This function is called twice for every sysrq op. The first call is queued to
  76.      * run as soon as possible and will turn the leds on. The second call is delayed
  77.          * and will turn the leds off.
  78.          *
  79.          * last_start_jiffies holds the jiffies value for the most recent activation so
  80.          * if it very recent this is the first call, otherwise it's the second
  81.          */
  82.     if (jiffies - last_start_jiffies < BLINK_DELAY) {
  83.         /* turn the leds on */
  84.         my_flip_leds();
  85.         my_set_beep(BEEP_ON);
  86.  
  87.         ret = schedule_delayed_work(&my_work, BLINK_DELAY);
  88.         if (!ret) {
  89.             printk(KERN_DEBUG "sysrq-visual: Failed to schedule delayed work");
  90.         }
  91.  
  92.         } else {
  93.         /* restore the leds */
  94.         my_flip_leds();
  95.         my_set_beep(BEEP_OFF);
  96.     }
  97. }
  98.  
  99. /**
  100.  * entry point for handling a magic SysRq
  101.  */
  102. void visual_handler (int key, struct tty_struct *tty) {
  103.     int ret;
  104.  
  105.     my_driver = vc_cons[fg_console].d->vc_tty->driver;
  106.     /*printk(KERN_DEBUG "sysrq-visual: tty driver magic %x\n", my_driver->magic);*/
  107.  
  108.     last_start_jiffies = jiffies;
  109.  
  110.     if (delayed_work_pending(&my_work)) {
  111.         /* in case a previous blinking is still in progress we'll cancel the 'off' event
  112.              * and reschedule it to run later, so the leds will remain on for longer
  113.              */
  114.         cancel_delayed_work(&my_work);
  115.         ret = schedule_delayed_work(&my_work, BLINK_DELAY);
  116.         if (!ret) {
  117.             printk(KERN_DEBUG "sysrq-visual: Failed to schedule delayed work");
  118.         }
  119.  
  120.     } else {
  121.         /*
  122.          * Schedule the LED blink to run as soon as possible
  123.          */
  124.         ret = schedule_delayed_work(&my_work, 0);
  125.         if (!ret) {
  126.             printk(KERN_DEBUG "sysrq-visual: Failed to schedule immediate work");
  127.         }
  128.     }
  129. }
  130.  
  131.  
  132.                        
  133. int init_module (void) {        
  134.         register_sysrq_key('v', &visual_op);
  135.        
  136.         printk(KERN_DEBUG "sysrq-visual loaded\n");
  137.         return 0;
  138. }
  139.  
  140.  
  141. void cleanup_module (void) {
  142.     cancel_delayed_work(&my_work);
  143.     flush_scheduled_work();
  144.  
  145.         unregister_sysrq_key('v', &visual_op);
  146.                
  147.         printk(KERN_DEBUG "sysrq-visual unloaded\n");
  148. }
  149.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement