3 鼠標解讀(2)(harib05c)
程序已經很清晰了,我們繼續解讀程序。首先對mouse_decode函數略加修改。
bootpack.c節選
struct MOUSE_DEC { unsigned char buf[3], phase; int x, y, btn; }; int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat) { if (mdec->phase == 0) { /* 等待鼠標的0xfa的階段 */ if (dat == 0xfa) { mdec->phase = 1; } return 0; } if (mdec->phase == 1) { /* 等待鼠標第一字節的階段 */ if ((dat & 0xc8) == 0x08) { /* 如果第一字節正確 */ mdec->buf[0] = dat; mdec->phase = 2; } return 0; } if (mdec->phase == 2) { /* 等待鼠標第二字節的階段 */ mdec->buf[1] = dat; mdec->phase = 3; return 0; } if (mdec->phase == 3) { /* 等待鼠標第三字節的階段 */ mdec->buf[2] = dat; mdec->phase = 1; mdec->btn = mdec->buf[0] & 0x07; mdec->x = mdec->buf[1]; mdec->y = mdec->buf[2]; if ((mdec->buf[0] & 0x10) ! = 0) { mdec->x |= 0xffffff00; } if ((mdec->buf[0] & 0x20) ! = 0) { mdec->y |= 0xffffff00; } mdec->y = - mdec->y; /* 鼠標的y方向與畫面符號相反 */ return 1; } return -1; /* 應該不會到這兒來 */ }
■■■■■
結構體里增加的幾個變量用于存放解讀結果。這幾個變量是x、y和btn,分別用于存放移動信息和鼠標按鍵狀態。
另外,筆者還修改了if(mdec->phase==1)語句。這個if語句,用于判斷第一字節對移動有反應的部分是否在0~3的范圍內;同時還要判斷第一字節對點擊有反應的部分是否在8~F的范圍內。如果這個字節的數據不在以上范圍內,它就會被舍去。
雖說基本上不這么做也行,但鼠標連線偶爾也會有接觸不良、即將斷線的可能,這時就會產生不該有的數據丟失,這樣一來數據會錯開一個字節。數據一旦錯位,就不能順利解讀,那問題可就大了。而如果添加上對第一字節的檢查,就算出了問題,鼠標也只是動作上略有失誤,很快就能糾正過來,所以筆者加上了這項檢查。
■■■■■
最后的if(mdec->phase==3)部分,是解讀處理的核心。鼠標鍵的狀態,放在buf[0]的低3位,我們只取出這3位。十六進制的0x07相當于二進制的00000111,因此通過與運算(&),可以很順利地取出低3位的值。
x和y,基本上是直接使用buf[1]和buf[2],但是需要使用第一字節中對鼠標移動有反應的幾位(參考第一節的敘述)信息,將x和y的第8位及第8位以后全部都設成1,或全部都保留為0。這樣就能正確地解讀x和y。
在解讀處理的最后,對y的符號進行了取反的操作。這是因為,鼠標與屏幕的y方向正好相反,為了配合畫面方向,就對y符號進行了取反操作。
■■■■■
這樣,鼠標數據的解讀就完成了。現在我們來修改一下顯示部分。
HariMain節選
} else if (fifo8_status(&mousefifo) ! = 0) { i = fifo8_get(&mousefifo); io_sti(); if (mouse_decode(&mdec, i) ! = 0) { /* 數據的3個字節都齊了,顯示出來 */ sprintf(s, "[lcr %4d %4d]", mdec.x, mdec.y); if ((mdec.btn & 0x01) ! = 0) { s[1] = 'L'; } if ((mdec.btn & 0x02) ! = 0) { s[3] = 'R'; } if ((mdec.btn & 0x04) ! = 0) { s[2] = 'C'; } boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 32, 16, 32 + 15 * 8-1, 31); putfonts8_asc(binfo->vram, binfo->scrnx, 32, 16, COL8_FFFFFF, s); } }
雖然程序中會檢查mdec.btn的值,用3個if語句將s的值置換成相應的字符串,不過這一部分,暫時先不要管了。這樣,程序就變成以下這樣。
sprintf(s, "[lcr %4d %4d]", mdec.x, mdec.y); boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 32, 16, 32 + 15 * 8-1, 31); putfonts8_asc(binfo->vram, binfo->scrnx, 32, 16, COL8_FFFFFF, s);
這與以前的程序很相似,僅僅用來顯示字符串。現在加上剛才的if語句:
if ((mdec.btn & 0x01) ! = 0) { s[1] = 'L'; }
這行程序的意思是,如果mdec.btn的最低位是1,就把s的第2個字符(注:第1個字符是s[0])換成‘L'。這就是將小寫字符置換成大寫字符。其他的if語句也都這樣理解吧。
■■■■■
執行一下看看。

反應都很正常,心情大好。
- Linux運維實戰:CentOS7.6操作系統從入門到精通
- 玩到極致 iPhone 4S完全攻略
- 深入理解eBPF與可觀測性
- RESS Essentials
- 網絡操作系統管理與應用(第三版)
- Mobile First Design with HTML5 and CSS3
- Dreamweaver CS5.5 Mobile and Web Development with HTML5,CSS3,and jQuery
- Delphi Programming Projects
- OpenSolaris設備驅動原理與開發
- Heroku Cloud Application Development
- 統信UOS應用開發進階教程
- 鴻蒙HarmonyOS應用開發入門
- Website Development with PyroCMS
- Getting Started with Raspberry Pi Zero
- Mastering AWS CloudFormation