kbleds.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /*
  2. * kbleds.c - Blink keyboard leds until the module is unloaded.
  3. */
  4. #include <linux/module.h>
  5. #include <linux/init.h>
  6. #include <linux/vt_kern.h> /* for fg_console */
  7. #include <linux/tty.h> /* For fg_console, MAX_NR_CONSOLES */
  8. #include <linux/kd.h> /* For KDSETLED */
  9. #include <linux/vt.h>
  10. #include <linux/console_struct.h> /* For vc_cons */
  11. MODULE_DESCRIPTION("Example module illustrating the use of Keyboard LEDs.");
  12. MODULE_AUTHOR("Daniele Paolo Scarpazza");
  13. MODULE_LICENSE("GPL");
  14. struct timer_list my_timer;
  15. struct tty_driver *my_driver;
  16. char kbledstatus = 0;
  17. #define BLINK_DELAY HZ/5
  18. #define ALL_LEDS_ON 0x07
  19. #define RESTORE_LEDS 0xFF
  20. /*
  21. * Function my_timer_func blinks the keyboard LEDs periodically by invoking
  22. * command KDSETLED of ioctl() on the keyboard driver. To learn more on virtual
  23. * terminal ioctl operations, please see file:
  24. * /usr/src/linux/drivers/char/vt_ioctl.c, function vt_ioctl().
  25. *
  26. * The argument to KDSETLED is alternatively set to 7 (thus causing the led
  27. * mode to be set to LED_SHOW_IOCTL, and all the leds are lit) and to 0xFF
  28. * (any value above 7 switches back the led mode to LED_SHOW_FLAGS, thus
  29. * the LEDs reflect the actual keyboard status). To learn more on this,
  30. * please see file:
  31. * /usr/src/linux/drivers/char/keyboard.c, function setledstate().
  32. *
  33. */
  34. static void my_timer_func(unsigned long ptr)
  35. {
  36. unsigned long *pstatus = (unsigned long *)ptr;
  37. struct tty_struct* t = vc_cons[fg_console].d->port.tty;
  38. if (*pstatus == ALL_LEDS_ON)
  39. *pstatus = RESTORE_LEDS;
  40. else
  41. *pstatus = ALL_LEDS_ON;
  42. (my_driver->ops->ioctl) (t, KDSETLED, *pstatus);
  43. my_timer.expires = jiffies + BLINK_DELAY;
  44. add_timer(&my_timer);
  45. }
  46. static int __init kbleds_init(void)
  47. {
  48. int i;
  49. pr_info("kbleds: loading\n");
  50. pr_info("kbleds: fgconsole is %x\n", fg_console);
  51. for (i = 0; i < MAX_NR_CONSOLES; i++) {
  52. if (!vc_cons[i].d)
  53. break;
  54. pr_info("poet_atkm: console[%i/%i] #%i, tty %lx\n", i,
  55. MAX_NR_CONSOLES, vc_cons[i].d->vc_num,
  56. (unsigned long)vc_cons[i].d->port.tty);
  57. }
  58. pr_info("kbleds: finished scanning consoles\n");
  59. my_driver = vc_cons[fg_console].d->port.tty->driver;
  60. pr_info("kbleds: tty driver magic %x\n", my_driver->magic);
  61. /*
  62. * Set up the LED blink timer the first time
  63. */
  64. timer_setup(&my_timer, (void*)&my_timer_func, (unsigned long)&kbledstatus);
  65. my_timer.expires = jiffies + BLINK_DELAY;
  66. add_timer(&my_timer);
  67. return 0;
  68. }
  69. static void __exit kbleds_cleanup(void)
  70. {
  71. pr_info("kbleds: unloading...\n");
  72. del_timer(&my_timer);
  73. (my_driver->ops->ioctl) (vc_cons[fg_console].d->port.tty,
  74. KDSETLED, RESTORE_LEDS);
  75. }
  76. module_init(kbleds_init);
  77. module_exit(kbleds_cleanup);