2010年5月4日

virtual user input


如果想模擬使用者操作滑鼠、鍵盤等輸入裝置,可利用二種方式:xdotool或uinput,以下分別介紹。

xdotool - command-line X11 auto mation tool
利用xlib functions所建構的程式,讓你可以模擬使用滑鼠、鍵盤,甚至視窗的放大縮小。以下script demo 一個滑鼠由左上角向右下方移動:
#! /bin/bash

declare -i i sum
xdotool mousemove 0 0
for ((i=1; i<=768; i=i+1))
do
  xdotool mousemove $i  $i
done

UINPUT - using uinput driver in Linux-2.6 to send user input Linux 2.6.x 支援"uinput"driver,它可幫助應用程式丟一些訊息給kernel,並且模擬成input device訊息。對於一些無線遙桿、無線遙桿介面實作十分有用。例如你的裝置是multi-touch controller,它遵循著window7 multi-touch format,你可在內核啟動EVDEV、HIDRAW、UINPUT這三個設定,然後寫一個daemon去讀hidraw device node的資料,接著再分析出多點的X、Y值及壓力值回傳到uinput device node,uinput driver 它就會幫你模擬成linux touch event。 以下程式demo一個滑鼠由右下方向左上角移動:
1)load uinput driver        
        #modprobe uinput
2)move you cursor to the lower right
3)develop a sample application as  
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <linux/input.h>
#include <linux/uinput.h>
#include <sys/time.h>

/* Globals */
struct uinput_user_dev uinp;
static int uinp_fd = -1;
struct uinput_user_dev uinp; // uInput device structure
struct input_event event; // Input device structure

/* Setup the uinput device */
int
setup_uinput_device ()
{
int i;
// Open the input device
uinp_fd = open ("/dev/uinput", O_WRONLY | O_NDELAY);
if (uinp_fd == 0)
{
printf ("Unable to open /dev/uinput\n");
return -1;
}
// Intialize the uInput device to NULL
memset (&uinp, 0, sizeof (uinp));
strncpy(uinp.name, "Virtual Mouse Device", strlen(
"Virtual Mouse Device"));
uinp.id.version = 4;
uinp.id.bustype = BUS_USB;
// Setup the uinput device
ioctl (uinp_fd, UI_SET_EVBIT, EV_REL);
ioctl (uinp_fd, UI_SET_RELBIT, REL_X);
ioctl (uinp_fd, UI_SET_RELBIT, REL_Y);
for (i = 0; i < 256; i++)
{
ioctl (uinp_fd, UI_SET_KEYBIT, i);
}
ioctl (uinp_fd, UI_SET_KEYBIT, BTN_MOUSE);

/* Create input device into input sub-system */
if(write (uinp_fd, &uinp, sizeof (uinp))!=sizeof(uinp))
{
printf ("First write returned fail.\n");
return -1;
}

if(ioctl (uinp_fd, UI_DEV_CREATE))
{
printf ("ioctl UI_DEV_CREATE returned fail.\n");
return -1;
}

return 1;
}

int
main (void)
{
int i;

if (setup_uinput_device () < 0)
{
printf ("Unable to find uinput device\n");
return -1;
}

// Test the uinput module
for (i = 0; i <= 768; i++)
{

struct timeval tv1;
struct timespec s;
s.tv_nsec = 5000000L;
s.tv_sec = 0;


// move pointer upleft by 1 pixel
memset (&event, 0, sizeof (event));
gettimeofday (&event.time, NULL);
event.type = EV_REL;
event.code = REL_X;
event.value = -1;
write (uinp_fd, &event, sizeof (event));

memset (&event, 0, sizeof (event));
gettimeofday (&event.time, NULL);
event.type = EV_REL;
event.code = REL_Y;
event.value = -1;
write (uinp_fd, &event, sizeof (event));

memset (&event, 0, sizeof (event));
gettimeofday (&event.time, NULL);
event.type = EV_SYN;
event.code = SYN_REPORT;
event.value = 0;
write (uinp_fd, &event, sizeof (event));

// wait just a moment
nanosleep (&s, NULL);

}
// destroy the device
ioctl (uinp_fd, UI_DEV_DESTROY);


close (uinp_fd);
}


Reference Using uinput driver in Linux-2.6.x send user input www.einfochips.com/download/dash_jan_tip.pdf

2.6.x to send user input

沒有留言: