电竞比分网-中国电竞赛事及体育赛事平台

分享

使用UInput模擬系統(tǒng)鍵盤鼠標(biāo)動(dòng)作

 quasiceo 2015-01-27
分類: Linux C 2012-04-18 11:47 1467人閱讀 評(píng)論(0) 收藏 舉報(bào)


1. 打開UInput Device:

應(yīng)用程序:

dev 為 UInput Node名:通常為/dev/uinput。

open(dev, O_WRONLY | O_NDELAY);

 

此時(shí),在Kernel 層,對(duì)應(yīng)的動(dòng)作為:

static int uinput_open(struct inode *inode, struct file *file)

參數(shù)inode對(duì)應(yīng)的是 主設(shè)備為10,子設(shè)備為223的node(即位用戶態(tài)的dev)

參數(shù)file對(duì)應(yīng)打開的文件。

動(dòng)作:

創(chuàng)建了newdev-- uinput_device結(jié)構(gòu)。

newdev->state = UIST_NEW_DEVICE; 

file->private_data = newdev;

 

 

2. 設(shè)置UInput Device:

ioctl(fd, UI_SET_EVBIT, EV_KEY);

此時(shí),在Kernel 層,對(duì)應(yīng)的動(dòng)作為:

static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)

參數(shù)file對(duì)應(yīng)打開的文件。

參數(shù)cmd 對(duì)應(yīng)用戶態(tài)ioctl參數(shù)2。UI_SET_EVBIT

參數(shù)arg對(duì)應(yīng)用戶態(tài)ioctl參數(shù)3。EV_KEY

動(dòng)作:

2.1 將driver參數(shù)傳遞過來。

udev = file->private_data;

udev->dev 是個(gè)input_dev 類型數(shù)據(jù)。 此時(shí),它未初始化。

如果udev->dev為空,則使用 uinput_allocate_device(udev);申請(qǐng)input_dev結(jié)構(gòu)

 

具體到CMD=UI_SET_EVBIT

uinput_set_bit(arg, evbit, EV_MAX);

首先判斷newdev->state為UIST_CREATED,則返回錯(cuò)誤碼。

這就說明:設(shè)置bit,需要在create input device 之前。

具體動(dòng)作為:udev->dev->evbit 設(shè)為EV_KEY.

 

注意:此處input device的evbit:

一個(gè)是evbit.表示設(shè)備所支持的動(dòng)作.

#define EV_KEY   0x01  // 按鍵
#define EV_REL   0x02  // 釋放

 

3.繼續(xù)設(shè)置 Device:

ret = ioctl(fd, UI_SET_RELBIT, REL_X); //鼠標(biāo)

ret = ioctl(fd, UI_SET_RELBIT, REL_Y);

ret = ioctl(fd, UI_SET_EVBIT, EV_ABS);
ret = ioctl(fd, UI_SET_ABSBIT, ABS_X);
ret = ioctl(fd, UI_SET_ABSBIT, ABS_Y);
ret = ioctl(fd, UI_SET_ABSBIT, ABS_PRESSURE);

同上。設(shè)置了Keybit等。

這里就是設(shè)置了Input Device關(guān)心或者說會(huì)產(chǎn)生的消息。

 

 

4. 寫入設(shè)備:

struct uinput_user_dev uinput;

uinput.id.version = 4;
uinput.id.bustype = BUS_USB;
uinput.absmin[ABS_X] = 0;
uinput.absmax[ABS_X] = 65535; //sam 把屏幕設(shè)為0-65535
uinput.absmin[ABS_Y] = 0;
uinput.absmax[ABS_Y] = 65535;
uinput.absmin[ABS_PRESSURE] = 0;
uinput.absmax[ABS_PRESSURE] = 0xfff;

ret = write(fd, &uinput, sizeof(uinput));

此時(shí),在Kernel 層,對(duì)應(yīng)的動(dòng)作為:

此時(shí)Device status為UIST_NEW_DEVICE

并將udev->dev 這個(gè)input device 具體化。初始化該input_dev。

之后,改變狀態(tài):

udev->state = UIST_SETUP_COMPLETE;

 

 

5.創(chuàng)建Input Device:

注意,此處是創(chuàng)建了Input Device。而不是UInput Device。

ioctl(fd, UI_DEV_CREATE);

 此時(shí),在Kernel 層,對(duì)應(yīng)的動(dòng)作為:

input_register_device(udev->dev); //向子系統(tǒng)注冊(cè)該設(shè)備,之后中斷時(shí)input_event()向子系統(tǒng)報(bào)告事件

udev->state = UIST_CREATED;

 

6. 向Input Device發(fā)送Event:

struct input_event event = {0};
 gettimeofday(&event.time, NULL);

 event.type  = EV_KEY;
 event.code  = key;
 event.value = press ? 1:0;
 write(fd, &event, sizeof(event));

 此時(shí),在Kernel 層,對(duì)應(yīng)的動(dòng)作為:

static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)

因?yàn)榇藭r(shí)state為UIST_CREATED

input_event(udev->dev, ev.type, ev.code, ev.value);

發(fā)送event.

 

 

總結(jié):

使用UInput的步驟為:

1. 打開設(shè)備。

2. 使用ioctl() 配置設(shè)備。

3. 使用write() 將input device信息設(shè)置好。

4. 使用ioctl(UI_DEV_CREATE)創(chuàng)建Input Device。(即使用write設(shè)置的)

5. 再使用write() 寫入event.

 

 

 

 

UInput添加的Input Device在/proc的反應(yīng):

#cat /proc/bus/input/device

I: Bus=0003 Vendor=0000 Product=0000 Version=0004
N: Name="uinput"
P: Phys=
S: Sysfs=/class/input/input6
H: Handlers=event1 mouse1
B: EV=f
B: KEY=400 0 670000 ffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
B: REL=3
B: ABS=1000003

解釋如下:

Bus=0003 Vendor=0000 Product=0000 Version=0004
這是在第一次write時(shí)設(shè)置的:

uinp.id.version = 4;
uinp.id.bustype = BUS_USB;

struct input_id {
 __u16 bustype;
 __u16 vendor;
 __u16 product;
 __u16 version;
};

 

EV=f



源地址:http://blog.sina.com.cn/s/blog_602f87700100llew.html

主題推薦
鼠標(biāo) 應(yīng)用程序 sizeof 結(jié)構(gòu) 應(yīng)用
猜你在找
虛擬鼠標(biāo)驅(qū)動(dòng)的實(shí)現(xiàn)
Win32_14__win32控件2__教你自學(xué)掌握所有控件的玩法
屏幕取詞技術(shù)實(shí)現(xiàn)原理與關(guān)鍵源碼
Chrome插件開發(fā)之一 搭建基本結(jié)構(gòu)
All-In-One Code Framework 中文版 2012-09-11
c# 中的按鍵消息
Nagios監(jiān)控mysql從庫報(bào)錯(cuò) libmysqlclientso18 cannot open shared object file No such
Delphi圖像處理 -- 灰色浮雕
EnumProcesses枚舉進(jìn)程
理解WebKit和Chromium 插件機(jī)制NPAPI Plugin

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多