Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* sysrq-visual.c
- *
- * Kernel module adding a magic SysRq handler that generates a visual response (flash the keyboard leds once),
- * so you know that magic SysRq is still there.
- *
- * I'm a kernel hacking newb so most of this was copied from examples and documentation.
- *
- * assaf d0t berg @t gmail dot c0m
- */
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/sysrq.h>
- #include <linux/kbd_kern.h>
- #include <linux/init.h>
- #include <linux/tty.h> /* For fg_console, MAX_NR_CONSOLES */
- #include <linux/kd.h> /* For KDSETLED */
- #include <linux/vt.h>
- #include <linux/vt_kern.h>
- #include <linux/console_struct.h> /* For vc_cons */
- #include <linux/workqueue.h>
- #define BLINK_DELAY HZ/5
- #define BEEP_ON ((125 << 16) + 1591)
- #define BEEP_OFF 0
- static void my_work_func(struct work_struct *);
- DECLARE_DELAYED_WORK(my_work, my_work_func);
- struct tty_driver *my_driver;
- static long last_start_jiffies = 0;
- /**
- * entry point for handling a magic SysRq
- */
- void visual_handler (int key, struct tty_struct *tty);
- /**
- * The SysRq op structure for our handler
- */
- struct sysrq_key_op visual_op = {
- handler: visual_handler,
- help_msg: "Visual",
- action_msg: "Blinking..."
- };
- /**
- * Set the led state using the given parameter
- */
- static void my_flip_leds(void) {
- char ledstatus = 0;
- (my_driver->ops->ioctl) (vc_cons[fg_console].d->vc_tty, NULL, KDGETLED,
- (unsigned long) &ledstatus);
- ledstatus = (~ledstatus) & 7;
- (my_driver->ops->ioctl) (vc_cons[fg_console].d->vc_tty, NULL, KDSETLED,
- ledstatus);
- }
- static void my_set_beep(int tone) {
- (my_driver->ops->ioctl) (vc_cons[fg_console].d->vc_tty, NULL, KDMKTONE,
- tone);
- }
- /**
- * function to to turn on the leds and reset the leds after a small delay
- */
- static void my_work_func(struct work_struct *ws)
- {
- int ret;
- /* This function is called twice for every sysrq op. The first call is queued to
- * run as soon as possible and will turn the leds on. The second call is delayed
- * and will turn the leds off.
- *
- * last_start_jiffies holds the jiffies value for the most recent activation so
- * if it very recent this is the first call, otherwise it's the second
- */
- if (jiffies - last_start_jiffies < BLINK_DELAY) {
- /* turn the leds on */
- my_flip_leds();
- my_set_beep(BEEP_ON);
- ret = schedule_delayed_work(&my_work, BLINK_DELAY);
- if (!ret) {
- printk(KERN_DEBUG "sysrq-visual: Failed to schedule delayed work");
- }
- } else {
- /* restore the leds */
- my_flip_leds();
- my_set_beep(BEEP_OFF);
- }
- }
- /**
- * entry point for handling a magic SysRq
- */
- void visual_handler (int key, struct tty_struct *tty) {
- int ret;
- my_driver = vc_cons[fg_console].d->vc_tty->driver;
- /*printk(KERN_DEBUG "sysrq-visual: tty driver magic %x\n", my_driver->magic);*/
- last_start_jiffies = jiffies;
- if (delayed_work_pending(&my_work)) {
- /* in case a previous blinking is still in progress we'll cancel the 'off' event
- * and reschedule it to run later, so the leds will remain on for longer
- */
- cancel_delayed_work(&my_work);
- ret = schedule_delayed_work(&my_work, BLINK_DELAY);
- if (!ret) {
- printk(KERN_DEBUG "sysrq-visual: Failed to schedule delayed work");
- }
- } else {
- /*
- * Schedule the LED blink to run as soon as possible
- */
- ret = schedule_delayed_work(&my_work, 0);
- if (!ret) {
- printk(KERN_DEBUG "sysrq-visual: Failed to schedule immediate work");
- }
- }
- }
- int init_module (void) {
- register_sysrq_key('v', &visual_op);
- printk(KERN_DEBUG "sysrq-visual loaded\n");
- return 0;
- }
- void cleanup_module (void) {
- cancel_delayed_work(&my_work);
- flush_scheduled_work();
- unregister_sysrq_key('v', &visual_op);
- printk(KERN_DEBUG "sysrq-visual unloaded\n");
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement