導航:首頁 > 操作系統 > linux模擬鍵盤輸入

linux模擬鍵盤輸入

發布時間:2023-01-27 11:11:14

linux下如何模擬按鍵輸入和模擬滑鼠

linux/input.h 中有定義,這個文件還定義了標准按鍵的編碼等 struct input_event { struct timeval time; //按鍵時間 __u16 type; //類型,在下面有定義 __u16 code; //要模擬成什麼按鍵 __s32 value;//是按下還是釋放 }; code: 事件的代碼.如果事件的類型代碼是EV_KEY,該代碼code 為設備鍵盤代碼.代碼植0~127 為鍵盤上的按鍵代碼,0x110~0x116 為滑鼠上按鍵代碼,其中0x110(BTN_ LEFT)為滑鼠左鍵,0x111(BTN_RIGHT)為滑鼠右鍵,0x112(BTN_ MIDDLE)為滑鼠中鍵.其它代碼含義請參看 include/linux/input.h 文件. 如果事件的類型代碼是EV_REL,code 值表示軌跡的類型.如指示滑鼠的X軸方向REL_X(代碼為0x00),指示滑鼠的Y 軸方向REL_Y(代碼為0x01),指示滑鼠中輪子方向 REL_WHEEL(代碼為0x08). type: EV_KEY,鍵盤 EV_REL,相對坐標 EV_ABS,絕對坐標 value: 事件的值.如果事件的類型代碼是EV_KEY,當按鍵按下時值為1,松開時值為0;如果事件的類型代碼是 EV_ REL,value 的正數值和負數值分別代表兩個不同方向的值. /* * Event types */ #define EV_SYN 0x00 #define EV_KEY 0x01 //按鍵 #define EV_REL 0x02 //相對坐標(軌跡球) #define EV_ABS 0x03 //絕對坐標 #define EV_MSC 0x04 //其他 #define EV_SW 0x05 #define EV_LED 0x11 //LED #define EV_SND 0x12//聲音 #define EV_REP 0x14//repeat #define EV_FF 0x15 #define EV_PWR 0x16 #define EV_FF_STATUS 0x17 #define EV_MAX 0x1f #define EV_CNT (EV_MAX+1) 1。模擬按鍵輸入 //其中0 表示釋放,1 按鍵按下,2 表示一直按下 //0 for EV_KEY for release, 1 for keypress and 2 for autorepeat. void simulate_key(int fd,int value) { struct input_event event; event.type = EV_KEY; //event.code = KEY_0;//要模擬成什麼按鍵 event.value = value;//是按下還是釋放按鍵或者重復 gettimeofday(&event.time,0); if(write(fd,&event,sizeof(event)) < 0){ dprintk("simulate key error~~~\n"); return ; } } 2。模擬滑鼠輸入(軌跡球) void simulate_mouse(int fd,char buf[4]) { int rel_x,rel_y; static struct input_event event,ev; //buf[0],buf[2],小於0 則為左移,大於0 則為右移 //buf[1],buf[3],小於0 則為下移,大於0 則為上移 dprintk("MOUSE TOUCH: x1=%d,y1=%d,x2=%d,y2=%d\n",buf[0],buf[1],buf[2],buf[3]); rel_x = (buf[0] + buf[2]) /2; rel_y = -(buf[1] + buf[3]) /2; //和我們的滑鼠是相反的方向,所以取反 event.type = EV_REL; event.code = REL_X; event.value = rel_x; gettimeofday(&event.time,0); if( write(fd,&event,sizeof(event))!=sizeof(event)) dprintk("rel_x error~~~:%s\n",strerror(errno)); event.code = REL_Y; event.value = rel_y; gettimeofday(&event.time,0); if( write(fd,&event,sizeof(event))!=sizeof(event)) dprintk("rel_y error~~~:%s\n",strerror(errno)); //一定要刷新空的 write(fd,&ev,sizeof(ev)); } 滑鼠和鍵盤文件打開方法: int fd_kbd; // /dev/input/event1 int fd_mouse; //dev/input/mouse2 fd_kbd = open("/dev/input/event1",O_RDWR); if(fd_kbdkey.window = window->window; //一定要設置為主窗口 event->key.keyval = keyval; //FIXME:一定要加上這個,要不然容易出錯 g_object_ref(event->key.window); gdk_threads_enter(); //FIXME: 記得用這個來發送事件 gtk_main_do_event(event); gdk_threads_leave(); gdk_event_free(event); } kernel 里input 模塊 input_dev 結構: struct input_dev { void *private; const char *name; const char *phys; const char *uniq; struct input_id id; /* * 根據各種輸入信號的類型來建立類型為unsigned long 的數組, * 數組的每1bit 代表一種信號類型, * 內核中會對其進行置位或清位操作來表示時間的發生和被處理. */ unsigned long evbit[NBITS(EV_MAX)]; unsigned long keybit[NBITS(KEY_MAX)]; unsigned long relbit[NBITS(REL_MAX)]; unsigned long absbit[NBITS(ABS_MAX)]; unsigned long mscbit[NBITS(MSC_MAX)]; unsigned long ledbit[NBITS(LED_MAX)]; unsigned long sndbit[NBITS(SND_MAX)]; unsigned long ffbit[NBITS(FF_MAX)]; unsigned long swbit[NBITS(SW_MAX)]; ......................................... }; /** * input_set_capability - mark device as capable of a certain event * @dev: device that is capable of emitting or accepting event * @type: type of the event (EV_KEY, EV_REL, etc...) * @code: event code * * In addition to setting up corresponding bit in appropriate capability * bitmap the function also adjusts dev->evbit. */ /* 記錄本設備對於哪些事件感興趣(對其進行處理)*/ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code) { switch (type) { case EV_KEY: __set_bit(code, dev->keybit);//比如按鍵,應該對哪些鍵值的按鍵進行處理(對於其它按鍵不予理睬) break; case EV_REL: __set_bit(code, dev->relbit); break; case EV_ABS: __set_bit(code, dev->absbit); break; case EV_MSC: __set_bit(code, dev->mscbit); break; case EV_SW: __set_bit(code, dev->swbit); break; case EV_LED: __set_bit(code, dev->ledbit); break; case EV_SND: __set_bit(code, dev->sndbit); break; case EV_FF: __set_bit(code, dev->ffbit); break; default: printk(KERN_ERR "input_set_capability: unknown type %u (code %u)\n", type, code); mp_stack(); return; } __set_bit(type, dev->evbit);//感覺和前面重復了(前面一經配置過一次了) } EXPORT_SYMBOL(input_set_capability); static irqreturn_t gpio_keys_isr(int irq, void *dev_id) { int i; struct platform_device *pdev = dev_id; struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; struct input_dev *input = platform_get_drvdata(pdev); for (i = 0; i < pdata->nbuttons; i++) { struct gpio_keys_button *button = &pdata->buttons[i]; int gpio = button->gpio; if (irq == gpio_to_irq(gpio)) {//判斷哪個鍵被按了? unsigned int type = button->type ?: EV_KEY; int state = (gpio_get_value(gpio) ? 1 : 0) ^ button->active_low;//記錄按鍵狀態 input_event(input, type, button->code, !!state);//匯報輸入事件 input_sync(input);//等待輸入事件處理完成 } } return IRQ_HANDLED; } /* * input_event() - report new input event * @dev: device that generated the event * @type: type of the event * @code: event code * @value: value of the event * * This function should be used by drivers implementing various input devices * See also input_inject_event() */ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { struct input_handle *handle; if (type > EV_MAX || !test_bit(type, dev->evbit))//首先判斷該事件類型是否有效且為該設備所接受 return; add_input_randomness(type, code, value); switch (type) { case EV_SYN: switch (code) { case SYN_CONFIG: if (dev->event) dev->event(dev, type, code, value); break; case SYN_REPORT: if (dev->sync) return; dev->sync = 1; break; } break; case EV_KEY: /* * 這里需要滿足幾個條件: * 1: 鍵值有效(不超出定義的鍵值的有效范圍) * 2: 鍵值為設備所能接受(屬於該設備所擁有的鍵值范圍) * 3: 按鍵狀態改變了 */ if (code > KEY_MAX || !test_bit(code, dev->keybit) || !!test_bit(code, dev->key) == value) return; if (value == 2) break; change_bit(code, dev->key);//改變對應按鍵的狀態 /* 如果你希望按鍵未釋放的時候不斷匯報按鍵事件的話需要以下這個(在簡單的gpio_keys 驅動中不需要這個,暫時不去分析) */ if (test_bit(EV_REP, dev->evbit) && dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] && dev->timer.data && value) { dev->repeat_key = code; mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_DELAY])); } break; ........................................................ if (type != EV_SYN) dev->sync = 0; if (dev->grab) dev->grab->handler->event(dev->grab, type, code, value); else /* * 循環調用所有處理該設備的handle(event,mouse,ts,joy 等), * 如果有進程打開了這些handle(進行讀寫),則調用其對應的event 介面向氣匯報該輸入事件. */ list_for_each_entry(handle, &dev->h_list, d_node) if (handle->open) handle->handler->event(handle, type, code, value); } EXPORT_SYMBOL(input_event); event 層對於input 層報告的這個鍵盤輸入事件的處理: drivers/input/evdev.c: static struct input_handler evdev_handler = { .event = evdev_event, .connect = evdev_connect, .disconnect = evdev_disconnect, .fops = &evdev_fops, .minor = EVDEV_MINOR_BASE, .name = "evdev", .id_table = evdev_ids, }; Linux 有自己的 input 子系統,可以統一管理滑鼠和鍵盤事件。 基於輸入子系統 實現的 uinput 可以方便的在用戶空間模擬滑鼠和鍵盤事件。 當然,也可以自己造輪子, 做一個字元設備接收用戶輸入,根據輸入,投遞 input 事件。 還有一種方式就是直接 往 evnent 里寫入數據, 都可以達到控制滑鼠鍵盤的功能。 本篇文章就是演示直接寫入 event 的方法。 linux/input.h 中有定義,這個文件還定義了標准按鍵的編碼等 struct input_event { struct timeval time; //按鍵時間 __u16 type; //類型,在下面有定義 __u16 code; //要模擬成什麼按鍵 __s32 value;//是按下還是釋放 }; code: 事件的代碼.如果事件的類型代碼是EV_KEY,該代碼code 為設備鍵盤代碼.代碼植0~127 為鍵盤上的按鍵代碼, 0x110~0x116 為滑鼠上按鍵代碼,其中0x110(BTN_ LEFT)為滑鼠左鍵,0x111(BTN_RIGHT)為滑鼠右鍵,0x112(BTN_ MIDDLE)為滑鼠中鍵.其它代碼含義請參看 include/linux /input.h 文件. 如果事件的類型代碼是EV_REL,code 值表示軌跡的類型.如指示滑鼠的X軸方向 REL_X (代碼為0x00),指示滑鼠的Y 軸方向REL_Y(代碼為0x01),指示滑鼠中輪子方向 REL_WHEEL(代碼為0x08). type: EV_KEY,鍵盤 EV_REL,相對坐標 EV_ABS,絕對坐標 value: 事件的值.如果事件的類型代碼是EV_KEY,當按鍵按下時值為1,松開時值為0;如果事件的類型代碼是 EV_ REL,value 的正數值和負數值分別代表兩個不同方向的值. /* * Event types */ #define EV_SYN 0x00 #define EV_KEY 0x01 //按鍵 #define EV_REL 0x02 //相對坐標(軌跡球) #define EV_ABS 0x03 //絕對坐標 #define EV_MSC 0x04 //其他 #define EV_SW 0x05 #define EV_LED 0x11 //LED #define EV_SND 0x12//聲音 #define EV_REP 0x14//repeat #define EV_FF 0x15 #define EV_PWR 0x16 #define EV_FF_STATUS 0x17 #define EV_MAX 0x1f #define EV_CNT (EV_MAX+1) 下面是一個模擬滑鼠和鍵盤輸入的例子: #include #include #include #include #include #include #include #include #include #include #include void simulate_key(int fd,int kval) { struct input_event event; event.type = EV_KEY; event.value = 1; event.code = kval; gettimeofday(&event.time,0); write(fd,&event,sizeof(event)) ; event.type = EV_SYN; event.code = SYN_REPORT; event.value = 0; write(fd, &event, sizeof(event)); memset(&event, 0, sizeof(event)); gettimeofday(&event.time, NULL); event.type = EV_KEY; event.code = kval; event.value = 0; write(fd, &event, sizeof(event)); event.type = EV_SYN; event.code = SYN_REPORT; event.value = 0; write(fd, &event, sizeof(event)); } void simulate_mouse(int fd) { struct input_event event; memset(&event, 0, sizeof(event)); gettimeofday(&event.time, NULL); event.type = EV_REL; event.code = REL_X; event.value = 10; write(fd, &event, sizeof(event)); event.type = EV_REL; event.code = REL_Y; event.value = 10; write(fd, &event, sizeof(event)); event.type = EV_SYN; event.code = SYN_REPORT; event.value = 0; write(fd, &event, sizeof(event)); } int main() { int fd_kbd; int fd_mouse; fd_kbd = open("/dev/input/event1",O_RDWR); if(fd_kbd

② 如何在linux下shell編寫腳本中模擬鍵盤輸入

用 yes 命令
如 yes 123 可以不停的輸出 123,你可以用 yes 123 | head -3 輸出三次。
然後你要是要對某個程序做輸入,你用輸入重定向。
如果你說的是應答,那就用 expect,具體的用法就復雜了,自己搜教程系統地學習吧。

閱讀全文

與linux模擬鍵盤輸入相關的資料

熱點內容
女主叫林晚晚男主叫沈池 瀏覽:934
小電影資源 瀏覽:668
踢米app怎麼建自習室 瀏覽:230
穿越的父女文 瀏覽:35
適合程序員的年會節目 瀏覽:494
法國電影love西瓜 瀏覽:129
韓國電影男的通過樓上洞偷窺女的跳舞 瀏覽:487
護生畫集pdf 瀏覽:613
韓劇女主是美容院老闆娘,為了生計和客戶 瀏覽:364
吳於廑pdf 瀏覽:543
父子訓誡虐心 瀏覽:781
文件解壓大於100m怎麼辦 瀏覽:184
紅姐和麗姐是什麼電影 瀏覽:277
島國小電影站點 瀏覽:788
mes程序員創業 瀏覽:934
劉智泰演的雙胞胎 瀏覽:610
日本電影校園男主最後死了 瀏覽:957
香港古裝艷情史 瀏覽:461
一個小男孩和一個小女孩離家出走的電影 瀏覽:942
小說主角陳凡 瀏覽:75