haribote mouse.c 鼠标管理程序阅读注释

Posted 资质平庸的程序员

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了haribote mouse.c 鼠标管理程序阅读注释相关的知识,希望对你有一定的参考价值。

[ 1] haribote ipl09.nas 引导程序阅读注释
[ 2] haribote asmhead.nas 从实模式进入保护模式程序阅读注释
[ 3] haribote dsctbl.c 设置GDT和IDT程序阅读注释
[ 4] haribote memory.c 内存管理程序阅读注释
[ 5] haribote int.c 可编程中断控制器(PIC)初始配置程序阅读注释
[ 6] haribote timer.c 定时器管理程序阅读注释
[ 7] haribote fifo.c 循环队列管理程序阅读注释
[ 8] haribote keyboard.c 键盘管理程序阅读注释

篇幅较长,可通过浏览器的搜索功能(Ctrl + f)搜索函数名了解相应函数的实现机制,如 mouse_decode。

[9] haribote mouse.c 鼠标管理程序阅读注释

mouse.c
/* mouse.c, 鼠标管理程序接口 */

/* 粗略理解鼠标和CPU的连接。
 *         =====
 *         |CPU|
 *         =====
 *           ↕
 * =======================
 * |     60h    64h      |
 * |---------------------|
 * |        8042         |
 * |---------------------|
 * |状态寄存器 控制寄存器|
 * |输入寄存器 输出寄存器|
 * =======================
 *           ↕
 *          ps/2
 *           ↕
 *    ===============
 *    | 键盘 | 鼠标 |
 *    ===============
 *  
 * CPU和8042芯片通过引脚直接相连,
 * 键盘设备(芯片)和鼠标设备(芯片)
 * 通过ps/2接口和8042相连。
 * 
 * 通过端口地址,CPU可直接和8042交
 * 互数据或命令。当CPU要与键盘或鼠
 * 标交互数据时需以8042作为桥梁,当
 * 8042接收到的CPU命令是与键盘或鼠
 * 标交互时,8042便充当这个中间桥梁。*/


#include "bootpack.h"

/* 管理鼠标缓冲队列的全局指针;
 * 标识鼠标缓冲队列中数据的全局变量。*/
struct FIFO32 *mousefifo;
int mousedata0;

/* inthandler2c,
 * 鼠标中断C处理函数,读取鼠标输入到鼠标缓冲队列中。
 * 
 * 当有鼠标输入而向PIC输出中断时,
 * CPU处理PIC申请的鼠标中断时会执行IDT[0x2c]中的处
 * 理函数_asm_inthandler2c(见int.c和dsctbl.c),该处
 * 理函数会调用此处的C处理函数inthandler2c。*/
void inthandler2c(int *esp)

    int data;
    
    /* 已差不多可正确读取鼠标数据时,
     * 设定PIC,向PIC发EOI命令时结束鼠标中断 */
    io_out8(PIC1_OCW2, 0x64);
    io_out8(PIC0_OCW2, 0x62);

    /* 读取鼠标数据并将其数据添加上鼠标标识
     * 后存入鼠标缓冲队列中,供其他任务读取 */
    data = io_in8(PORT_KEYDAT);
    fifo32_put(mousefifo, data + mousedata0);
    return;


/* KEYCMD_SENDTO_MOUSE,
 * 写鼠标命令,具体的鼠标命令随后由60h端口下发;
 *
 * MOUSECMD_ENABLE,开启鼠标发送数据功能的命令。*/
#define KEYCMD_SENDTO_MOUSE 0xd4
#define MOUSECMD_ENABLE     0xf4

/* enable_mouse,
 * 初始化键盘控制器使能鼠标并设置鼠标缓冲队列和鼠标数据标识。*/
void enable_mouse(struct FIFO32 *fifo, int data0, struct MOUSE_DEC *mdec)

    mousefifo = fifo;
    mousedata0 = data0;
    
    /* 等待键盘输入缓冲器空闲, 若键盘空闲则
     * 通过8042下发使能鼠标的命令到鼠标设备上。*/
    wait_KBC_sendready();
    io_out8(PORT_KEYCMD, KEYCMD_SENDTO_MOUSE);
    wait_KBC_sendready();
    io_out8(PORT_KEYDAT, MOUSECMD_ENABLE);

    /* 使能鼠标后,鼠标将会回复0xfa的消息;
     * 置phase=0标识鼠标中断传送的信息为0xfa。*/
    mdec->phase = 0;
    return;


/* mouse_decode,
 * 解析鼠标数据dat,将解析结果存于mdec指向的结构体中。
 *
 * 鼠标被操作时会向PIC输出中断信号, 中断C处理函数inthandler2c
 * 在每次鼠标中断发生时就从8042输出寄存器中读取一字节鼠标数据,
 * 鼠标以3字节为一组。
 * 
 * 当每读满3字节并完成解析时mouse_decode返回1;若鼠标数据解析失
 * 败则返回-1,若还未解析满3字节则返回0。*/
int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat)

    if (mdec->phase == 0) 
        /* 在phase=0时,表处于等待鼠标回复0xfa
         * 阶段,等到则置接收鼠标第一个字节数据阶段。*/
        if (dat == 0xfa) 
            mdec->phase = 1;
        
        return 0;
    
    if (mdec->phase == 1) 
        /* dat鼠标第1字节数据 */
        if ((dat & 0xc8) == 0x08) 
            /* 据作者观察(当然此文也观察过), 鼠标第1字
             * 节数据bit[3]=1,bit[7..6]=00,若鼠标第1字
             * 节数据不满足以上状态则表明 鼠标数据传递
             * 可能有误,所以在此丢弃并继续等待并解析第
             * 一字节数据。
             * 
             * bit[2..0]置位时分别代表鼠标滑轮点击, 鼠
             * 标右击和鼠标左击。bit[5..4]分别跟鼠标上
             * 下和左右移动的方向, 值为0时表示往上或右
             * 移动,值为1时表示往下或左移动。
             * 
             * 接收到第一个字节后置phase=2表示接下来接
             * 收鼠标第二字节数据。*/
            mdec->buf[0] = dat;
            mdec->phase = 2;
        
        return 0;
    
    if (mdec->phase == 2) 
        /* 接收鼠标第二字节数据(左右移动)并置
         * phase=3以接收鼠标第三字节数据。*/
        mdec->buf[1] = dat;
        mdec->phase = 3;
        return 0;
    
    if (mdec->phase == 3) 
        /* 鼠标第3字节数据接收完毕,置phase=1
         * 表继续接收下一组鼠标数据。*/
        mdec->buf[2] = dat;
        mdec->phase = 1;
    
        /* 一组鼠标数据接收完毕,开始解析。*/

        /* btn,点击事件;x,左右移动位移量;
         * y,上下移动位移量。*/
        mdec->btn = mdec->buf[0] & 0x07;
        mdec->x = mdec->buf[1];
        mdec->y = mdec->buf[2];
        
        /* 若鼠标第1字节bit[5..4]皆为1,则表示鼠标分别
         * 在往下或左方向移动, 鼠标将这两个方向分别视
         * 为y和x的负方向。与此对应, 此时鼠标中断传送
         * 上来的y和x是一个负数( 的低8位)。在32位补码
         * 表示数中, 将y和x的高24位扩展为1时, 就得到y
         * 和x的负数值, 从而获得了鼠标位移的真实值。*/
        if ((mdec->buf[0] & 0x10) != 0) 
            mdec->x |= 0xffffff00;
        
        if ((mdec->buf[0] & 0x20) != 0) 
            mdec->y |= 0xffffff00;
        
        
        /* 屏幕显示画面时原点在左上角,而鼠
         * 标移动位移量的原点在屏幕左下角。
         * 所以鼠标在y方向的位移值方向跟屏
         * 幕实际坐标方向相反,所以此处进行
         * 符号取反。*/
        mdec->y = - mdec->y;
        return 1;
    
    return -1;

bootpack.h
/* ... */

/* mouse.c */
/* struct MOUSE_DEC,
 * 用于存储鼠标输入数据及其解析结果的结构体类型。*/
struct MOUSE_DEC 
/* buf,用于保存鼠标的一组数据,共3字节;
 * phase,标识一组鼠标数据已输入多少字节;
 * 
 * 后面3个成员用于存储buf中鼠标数据的解析结果。
 * x和y,分别存储鼠标左右和上下移动的位移量;
 * btn,存储鼠标点击事件。*/
    unsigned char buf[3], phase;
    int x, y, btn;
;
void inthandler2c(int *esp);
void enable_mouse(struct FIFO32 *fifo, int data0, struct MOUSE_DEC *mdec);
int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat);

/* ... */

以上是关于haribote mouse.c 鼠标管理程序阅读注释的主要内容,如果未能解决你的问题,请参考以下文章

haribote sheet.c 窗口画面及显示管理程序阅读注释

haribote file.c 文件读取程序阅读注释

haribote bootpack.c 主任务程序代码阅读注释

haribote naskfunc.nas 汇编函数接口程序阅读注释

haribote window.c 自制窗口画面信息程序阅读注释

haribote graphic.c 由像素点阵转换显卡画面信息程序阅读注释