82 lines
2.6 KiB
C
82 lines
2.6 KiB
C
/*
|
||
* kbleds.c - 闪烁键盘LED直到模块被卸载。
|
||
*/
|
||
|
||
#include <linux/init.h>
|
||
#include <linux/kd.h> /* 引入 KDSETLED */
|
||
#include <linux/module.h>
|
||
#include <linux/tty.h> /* 引入 tty_struct */
|
||
#include <linux/vt.h> /* 引入 MAX_NR_CONSOLES */
|
||
#include <linux/vt_kern.h> /* 引入 fg_console */
|
||
#include <linux/console_struct.h> /* 引入 vc_cons */
|
||
|
||
MODULE_DESCRIPTION("示例模块,演示如何使用键盘LED。");
|
||
|
||
static struct timer_list my_timer;
|
||
static struct tty_driver *my_driver;
|
||
static unsigned long kbledstatus = 0;
|
||
|
||
#define BLINK_DELAY HZ / 5
|
||
#define ALL_LEDS_ON 0x07
|
||
#define RESTORE_LEDS 0xFF
|
||
|
||
/* 函数 my_timer_func 定期闪烁键盘LED,通过在键盘驱动上调用 ioctl() 命令 KDSETLED 实现。
|
||
* 要了解更多关于虚拟终端 ioctl 操作的信息,请参见文件:drivers/tty/vt/vt_ioctl.c, 函数 vt_ioctl()
|
||
*
|
||
* KDSETLED 的参数交替设置为 7(从而使 LED 模式设置为 LED_SHOW_IOCTL,所有的 LED 都被点亮)和 0xFF
|
||
* (任何大于 7 的值会将 LED 模式切换回 LED_SHOW_FLAGS,因此 LED 反映实际的键盘状态)。要了解更多信息,
|
||
* 请参见文件:drivers/tty/vt/keyboard.c, 函数 setledstate()。
|
||
*/
|
||
static void my_timer_func(struct timer_list *unused)
|
||
{
|
||
struct tty_struct *t = vc_cons[fg_console].d->port.tty;
|
||
|
||
if (kbledstatus == ALL_LEDS_ON)
|
||
kbledstatus = RESTORE_LEDS;
|
||
else
|
||
kbledstatus = ALL_LEDS_ON;
|
||
|
||
(my_driver->ops->ioctl)(t, KDSETLED, kbledstatus);
|
||
|
||
my_timer.expires = jiffies + BLINK_DELAY;
|
||
add_timer(&my_timer);
|
||
}
|
||
|
||
static int __init kbleds_init(void)
|
||
{
|
||
int i;
|
||
|
||
pr_info("kbleds: 正在加载\n");
|
||
pr_info("kbleds: 前台控制台为 %x\n", fg_console);
|
||
for (i = 0; i < MAX_NR_CONSOLES; i++) {
|
||
if (!vc_cons[i].d)
|
||
break;
|
||
pr_info("poet_atkm: 控制台[%i/%i] #%i, tty %p\n", i, MAX_NR_CONSOLES,
|
||
vc_cons[i].d->vc_num, (void *)vc_cons[i].d->port.tty);
|
||
}
|
||
pr_info("kbleds: 扫描控制台完成\n");
|
||
|
||
my_driver = vc_cons[fg_console].d->port.tty->driver;
|
||
pr_info("kbleds: tty 驱动程序名称 %s\n", my_driver->driver_name);
|
||
|
||
/* 设置 LED 闪烁定时器。 */
|
||
timer_setup(&my_timer, my_timer_func, 0);
|
||
my_timer.expires = jiffies + BLINK_DELAY;
|
||
add_timer(&my_timer);
|
||
|
||
return 0;
|
||
}
|
||
|
||
static void __exit kbleds_cleanup(void)
|
||
{
|
||
pr_info("kbleds: 正在卸载...\n");
|
||
del_timer(&my_timer);
|
||
(my_driver->ops->ioctl)(vc_cons[fg_console].d->port.tty, KDSETLED,
|
||
RESTORE_LEDS);
|
||
}
|
||
|
||
module_init(kbleds_init);
|
||
module_exit(kbleds_cleanup);
|
||
|
||
MODULE_LICENSE("GPL");
|