2021-07-22 06:35:24 +08:00
|
|
|
/*
|
|
|
|
* kbleds.c - Blink keyboard leds until the module is unloaded.
|
|
|
|
*/
|
|
|
|
|
2021-07-22 06:58:13 +08:00
|
|
|
#include <linux/console_struct.h> /* For vc_cons */
|
2021-07-22 06:35:24 +08:00
|
|
|
#include <linux/init.h>
|
2021-07-22 06:58:13 +08:00
|
|
|
#include <linux/kd.h> /* For KDSETLED */
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/tty.h> /* For fg_console, MAX_NR_CONSOLES */
|
2021-07-22 06:35:24 +08:00
|
|
|
#include <linux/vt.h>
|
2021-07-22 06:58:13 +08:00
|
|
|
#include <linux/vt_kern.h> /* for fg_console */
|
2021-07-22 06:35:24 +08:00
|
|
|
|
|
|
|
MODULE_DESCRIPTION("Example module illustrating the use of Keyboard LEDs.");
|
|
|
|
MODULE_AUTHOR("Daniele Paolo Scarpazza");
|
|
|
|
MODULE_LICENSE("GPL");
|
|
|
|
|
|
|
|
struct timer_list my_timer;
|
|
|
|
struct tty_driver *my_driver;
|
|
|
|
char kbledstatus = 0;
|
|
|
|
|
2021-07-22 06:58:13 +08:00
|
|
|
#define BLINK_DELAY HZ / 5
|
|
|
|
#define ALL_LEDS_ON 0x07
|
|
|
|
#define RESTORE_LEDS 0xFF
|
2021-07-22 06:35:24 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Function my_timer_func blinks the keyboard LEDs periodically by invoking
|
|
|
|
* command KDSETLED of ioctl() on the keyboard driver. To learn more on virtual
|
|
|
|
* terminal ioctl operations, please see file:
|
|
|
|
* /usr/src/linux/drivers/char/vt_ioctl.c, function vt_ioctl().
|
|
|
|
*
|
|
|
|
* The argument to KDSETLED is alternatively set to 7 (thus causing the led
|
|
|
|
* mode to be set to LED_SHOW_IOCTL, and all the leds are lit) and to 0xFF
|
|
|
|
* (any value above 7 switches back the led mode to LED_SHOW_FLAGS, thus
|
|
|
|
* the LEDs reflect the actual keyboard status). To learn more on this,
|
|
|
|
* please see file:
|
|
|
|
* /usr/src/linux/drivers/char/keyboard.c, function setledstate().
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void my_timer_func(unsigned long ptr)
|
|
|
|
{
|
2021-07-22 06:58:13 +08:00
|
|
|
unsigned long *pstatus = (unsigned long *) ptr;
|
|
|
|
struct tty_struct *t = vc_cons[fg_console].d->port.tty;
|
2021-07-22 06:35:24 +08:00
|
|
|
|
|
|
|
if (*pstatus == ALL_LEDS_ON)
|
|
|
|
*pstatus = RESTORE_LEDS;
|
|
|
|
else
|
|
|
|
*pstatus = ALL_LEDS_ON;
|
|
|
|
|
2021-07-22 06:58:13 +08:00
|
|
|
(my_driver->ops->ioctl)(t, KDSETLED, *pstatus);
|
2021-07-22 06:35:24 +08:00
|
|
|
|
|
|
|
my_timer.expires = jiffies + BLINK_DELAY;
|
|
|
|
add_timer(&my_timer);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __init kbleds_init(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
pr_info("kbleds: loading\n");
|
|
|
|
pr_info("kbleds: fgconsole is %x\n", fg_console);
|
|
|
|
for (i = 0; i < MAX_NR_CONSOLES; i++) {
|
|
|
|
if (!vc_cons[i].d)
|
|
|
|
break;
|
2021-07-22 06:58:13 +08:00
|
|
|
pr_info("poet_atkm: console[%i/%i] #%i, tty %lx\n", i, MAX_NR_CONSOLES,
|
|
|
|
vc_cons[i].d->vc_num, (unsigned long) vc_cons[i].d->port.tty);
|
2021-07-22 06:35:24 +08:00
|
|
|
}
|
|
|
|
pr_info("kbleds: finished scanning consoles\n");
|
|
|
|
|
|
|
|
my_driver = vc_cons[fg_console].d->port.tty->driver;
|
|
|
|
pr_info("kbleds: tty driver magic %x\n", my_driver->magic);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up the LED blink timer the first time
|
|
|
|
*/
|
2021-07-22 06:58:13 +08:00
|
|
|
timer_setup(&my_timer, (void *) &my_timer_func,
|
|
|
|
(unsigned long) &kbledstatus);
|
2021-07-22 06:35:24 +08:00
|
|
|
my_timer.expires = jiffies + BLINK_DELAY;
|
|
|
|
add_timer(&my_timer);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void __exit kbleds_cleanup(void)
|
|
|
|
{
|
|
|
|
pr_info("kbleds: unloading...\n");
|
|
|
|
del_timer(&my_timer);
|
2021-07-22 06:58:13 +08:00
|
|
|
(my_driver->ops->ioctl)(vc_cons[fg_console].d->port.tty, KDSETLED,
|
|
|
|
RESTORE_LEDS);
|
2021-07-22 06:35:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
module_init(kbleds_init);
|
|
|
|
module_exit(kbleds_cleanup);
|