linux ps2键盘驱动,通用键盘鼠标模拟(包括USB和PS2)
通過直接調(diào)用Kbdclass的回調(diào)函數(shù)KeyboardClassServiceCallback直接給上層發(fā)送鍵盤驅(qū)動。這個方法網(wǎng)上已經(jīng)公開,參考Hook KeyboardClassServiceCallback實現(xiàn)鍵盤 Logger,其他的還有很多,可以到網(wǎng)上去查。
簡單說一下沒有公開的部分,就是按下和松開的模擬,已經(jīng)擴展鍵的模擬。
模擬主要是構(gòu)造KEYBOARD_INPUT_DATA結(jié)構(gòu),按下和松開的Flags分別對應(yīng)KEY_MAKE、KEY_BREAK,然后調(diào)用KeyboardClassServiceCallback。這里直接用的sudami的代碼,在此謝過,懶得改了。代碼如下:
case IOCTL_KEY_DOWN :
{
if (ioBuf)
{
lKeyCode = *(ULONG*)ioBuf;
dprintf("[KeyMouse] KeymouseDispatchDeviceControl IOCTL_KEY_DOWN = 0x%x/n", lKeyCode);
dwSize = sizeof(KEYBOARD_INPUT_DATA);
__asm {
push eax
mov kid.UnitId,0 ; 構(gòu)造 KEYBOARD_INPUT_DATA
mov eax,lKeyCode
mov kid.MakeCode,ax
mov kid.Flags,KEY_MAKE ;模擬按下
mov kid.Reserved,0
mov kid.ExtraInformation,0
lea eax,dwRet
push eax
lea eax,kid
add eax,dwSize
push eax
lea eax,kid
push eax
push g_kbDeviceObject
call orig_KeyboardClassServiceCallback ;利用 KeyboardClassServiceCallback 模擬按鍵
pop eax
}
status = STATUS_SUCCESS;
}
break;
}
case IOCTL_KEY_UP:
{
if (ioBuf)
{
lKeyCode = *(ULONG*)ioBuf;
dprintf("[KeyMouse] KeymouseDispatchDeviceControl IOCTL_KEY_UP = 0x%x/n", lKeyCode);
dwSize = sizeof(KEYBOARD_INPUT_DATA);
__asm {
push eax
mov kid.UnitId,0 ; 構(gòu)造 KEYBOARD_INPUT_DATA
mov eax,lKeyCode
mov kid.MakeCode,ax
mov kid.Flags,KEY_BREAK ;模擬松開
mov kid.Reserved,0
mov kid.ExtraInformation,0
lea eax,dwRet
push eax
lea eax,kid
add eax,dwSize
push eax
lea eax,kid
push eax
push g_kbDeviceObject
call orig_KeyboardClassServiceCallback ;利用 KeyboardClassServiceCallback 模擬按鍵
pop eax
}
status = STATUS_SUCCESS;
}
break;
}
擴展鍵的區(qū)別是按下和松開的Flags分別對應(yīng)KEY_E0、KEY_E1。其他和上面的一樣,這里就不貼代碼出來了。主要說一下擴展鍵有哪幾個:(前面是MakeCode,后面代表按鈕)
0x1D-RIGHT CONTROL 0x38-RIGHT ALT 0x48-↑ 鍵 0x50-↓ 鍵 0x4b-← 鍵 0x4d-→ 鍵 0x5B-LEFT WIN 0x5C-RIGHT WIN
重點說一下鼠標(biāo)的模擬,原理和鍵盤的一樣。查找驅(qū)動mouclass.sys中的MouseClassServiceCallback函數(shù),然后獲取//Device//PointerClass0設(shè)備對象指針,構(gòu)造MOUSE_INPUT_DATA結(jié)構(gòu),然后調(diào)用MouseClassServiceCallback。難點就在與構(gòu)造MOUSE_INPUT_DATA結(jié)構(gòu)上面。
typedef struct _MOUSE_INPUT_DATA {
USHORT UnitId;
USHORT Flags;
union {
ULONG Buttons;
struct {
USHORT ButtonFlags;
USHORT ButtonData;
};
};
ULONG RawButtons;
LONG LastX;
LONG LastY;
ULONG ExtraInformation;
} MOUSE_INPUT_DATA, *PMOUSE_INPUT_DATA;
通過調(diào)試操作系統(tǒng)調(diào)用MouseClassServiceCallback的參數(shù),主要的標(biāo)示有3個。
Flags標(biāo)志是標(biāo)示鼠標(biāo)的坐標(biāo)屬性(即相對坐標(biāo)、絕對坐標(biāo)等)
ButtonFlags標(biāo)志是左右中鍵按下和松開的標(biāo)志
LastX是鼠標(biāo)X坐標(biāo),與Flags標(biāo)志有關(guān)
LastY是鼠標(biāo)Y坐標(biāo),與Flags標(biāo)志有關(guān)
其他幾項可以填0。
具體模擬代碼如下:
case IOCTL_MOUSE_LEFT_BUTTON_DOWN:
{
MouseFlags = MOUSE_LEFT_BUTTON_DOWN;
goto __MouseCallBack;
}
case IOCTL_MOUSE_LEFT_BUTTON_UP:
{
MouseFlags = MOUSE_LEFT_BUTTON_UP;
goto __MouseCallBack;
}
case IOCTL_MOUSE_RIGHT_BUTTON_DOWN:
{
MouseFlags = MOUSE_RIGHT_BUTTON_DOWN;
goto __MouseCallBack;
}
case IOCTL_MOUSE_RIGHT_BUTTON_UP:
{
MouseFlags = MOUSE_RIGHT_BUTTON_UP;
goto __MouseCallBack;
}
case IOCTL_MOUSE_MIDDLE_BUTTON_DOWN:
{
MouseFlags = MOUSE_MIDDLE_BUTTON_DOWN;
goto __MouseCallBack;
}
case IOCTL_MOUSE_MIDDLE_BUTTON_UP:
{
MouseFlags = MOUSE_MIDDLE_BUTTON_UP;
__MouseCallBack:
mid.UnitId = 0;
mid.Flags = MOUSE_MOVE_RELATIVE;
mid.Buttons = 0;
mid.ButtonFlags = MouseFlags;
mid.RawButtons = 0;
mid.LastX = *((ULONG*)ioBuf);
mid.LastY = *((ULONG*)ioBuf+1);
mid.ExtraInformation = 0;
InputDataStart = ∣
InputDataEnd = InputDataStart+1;
orig_MouseClassServiceCallback(
g_mouDeviceObject,
InputDataStart,
InputDataEnd,
&InputDataConsumed
);
status = STATUS_SUCCESS;
break;
}
case IOCTL_MOUSE_MOVE_RELATIVE:
{
mid.Flags = MOUSE_MOVE_RELATIVE; //相對坐標(biāo)
goto __MouseMoveCallBack;
}
case IOCTL_MOUSE_MOVE_ABSOLUTE:
{
mid.Flags = MOUSE_MOVE_ABSOLUTE; //絕對坐標(biāo)
goto __MouseMoveCallBack;
}
case IOCTL_MOUSE_VIRTUAL_DESKTOP:
{
mid.Flags = MOUSE_VIRTUAL_DESKTOP; //虛擬桌面
__MouseMoveCallBack:
mid.UnitId = 1;
mid.Buttons = 0;
mid.RawButtons = 0;
mid.LastX = *((ULONG*)ioBuf);
mid.LastY = *((ULONG*)ioBuf+1);
mid.ExtraInformation = 0;
InputDataStart = ∣
InputDataEnd = InputDataStart+1;
orig_MouseClassServiceCallback(
g_mouDeviceObject,
InputDataStart,
InputDataEnd,
&InputDataConsumed
);
status = STATUS_SUCCESS;
break;
}
驅(qū)動在windows XP SP2上測試通過。
總結(jié)
以上是生活随笔為你收集整理的linux ps2键盘驱动,通用键盘鼠标模拟(包括USB和PS2)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php图形验证码接口,php生成图形验证
- 下一篇: 12v小型电机型号大全_电动机型号参数大