从零开始操作系统-09:键盘实现

这一节主要主要是键盘。

所需要的文件在Github:https://github.com/yongkangluo/Ubuntu20.04OS/tree/main/Files/Lec7-ExternalInterrupt

  1. 初始化8042控制器
  2. 将键盘的硬件数据抽象封装
  3. 将封装好的键盘事件传送到上层

在初始化8042时,不仅仅需要发送命令,同时要等待返回代码。

static uint8_t ps2_issue_cmd(char cmd, uint16_t arg) {
	// 发送命令
    ps2_post_cmd(PS2_PORT_CTRL_CMDREG, cmd, arg);
    char result;
    // 等待PS/2控制器返回。通过轮询(polling)状态寄存器的 bit 0
    // 如置位,则表明返回代码此时就在 0x60 IO口上等待读取。
    // 判断是否成功
    while(!((result = io_inb(PS2_PORT_CTRL_STATUS)) & PS2_STATUS_OFULL));
    return io_inb(PS2_PORT_ENC_CMDREG);
}

static void ps2_post_cmd(uint8_t port, char cmd, uint16_t arg) {
    char result;
    // 等待PS/2输入缓冲区清空,这样我们才可以写入命令
    while((result = io_inb(PS2_PORT_CTRL_STATUS)) & PS2_STATUS_IFULL);
    io_outb(port, cmd);
    if (!(arg & PS2_NO_ARG)) {
        // 所有参数一律通过0x60传入。
        io_outb(PS2_PORT_ENC_CMDREG, (uint8_t)(arg & 0x00ff));
    }
}

	//关中断
    cpu_disable_interrupt();
    // 1、禁用任何的PS/2设备
    // 读取20 读取配置字节
    ps2_post_cmd(PS2_PORT_CTRL_CMDREG, PS2_CMD_PORT1_DISABLE, PS2_NO_ARG);
    // 禁用0 1
    ps2_post_cmd(PS2_PORT_CTRL_CMDREG, PS2_CMD_PORT2_DISABLE, PS2_NO_ARG);
    // 2、清空控制器缓冲区
    io_inb(PS2_PORT_ENC_DATA);
    char result;
    // 3、屏蔽所有PS/2设备(端口1&2)IRQ,并且禁用键盘键码转换功能
    result = ps2_issue_cmd(PS2_CMD_READ_CFG, PS2_NO_ARG);
    result = result & ~(PS2_CFG_P1INT | PS2_CFG_P2INT | PS2_CFG_TRANSLATION);
    ps2_post_cmd(PS2_PORT_CTRL_CMDREG, PS2_CMD_WRITE_CFG, result);
    // 4、控制器自检
    result = ps2_issue_cmd(PS2_CMD_SELFTEST, PS2_NO_ARG);
    if (result != PS2_RESULT_TEST_OK) {
        kprintf(KERROR "Controller self-test failed.");
        goto done;
    }
    // 5、设备自检(端口1自检,通常是我们的键盘)
    result = ps2_issue_cmd(PS2_CMD_SELFTEST_PORT1, PS2_NO_ARG);
    if (result != 0) {
        kprintf(KERROR "Interface test on port 1 failed.");
        goto done;
    }

    // 6、开启位于端口1的 IRQ,并启用端口1。不用理会端口2,那儿一般是鼠标。
    ps2_post_cmd(PS2_PORT_CTRL_CMDREG, PS2_CMD_PORT1_ENABLE, PS2_NO_ARG);
    result = ps2_issue_cmd(PS2_CMD_READ_CFG, PS2_NO_ARG);
    result = result | PS2_CFG_P1INT;
    ps2_post_cmd(PS2_PORT_CTRL_CMDREG, PS2_CMD_WRITE_CFG, result);
    // 至此,PS/2控制器和设备已完成初始化,可以正常使用。

键盘事件被封装成:

struct kdb_keyinfo_pkt {
    kbd_scancode_t scancode;//扫描码
    kbd_keycode_t keycode;//键码
    kbd_kstate_t state;//键盘状态
    time_t timestamp;//时间戳
};

注意:大小写锁定,shift、ctrl键等,不会被设置成信报,而是设置为状态。

设计要点:

  1. 哪些键是按下的,哪些是释放的
  2. 一些开关状态,大小写锁定
  3. 一些短暂状态,识别组合键
  4. 跟踪shift
  5. 一些扫描码由两个字节构成

向上层报告:

利用一个有界的缓存队列。使用一个读指针和写指针。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值