1 /* vdagentd-uinput.c vdagentd uinput handling code
3 Copyright 2010 Red Hat, Inc.
6 Hans de Goede <hdegoede@redhat.com>
7 Gerd Hoffmann <kraxel@redhat.com>
9 This program is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 #include <linux/input.h>
30 #include <linux/uinput.h>
31 #include <spice/vd_agent.h>
33 static int tablet
= -1;
35 void uinput_setup(const char *uinput_devname
, int width
, int height
)
37 struct uinput_user_dev device
= {
38 .name
= "spice vdagent tablet",
39 .absmax
[ ABS_X
] = width
,
40 .absmax
[ ABS_Y
] = height
,
47 tablet
= open(uinput_devname
, O_RDWR
);
49 fprintf(stderr
, "open %s: %s\n", uinput_devname
, strerror(errno
));
53 rc
= write(tablet
, &device
, sizeof(device
));
54 if (rc
!= sizeof(device
)) {
55 fprintf(stderr
, "%s: write error\n", __FUNCTION__
);
60 ioctl(tablet
, UI_SET_EVBIT
, EV_KEY
);
61 ioctl(tablet
, UI_SET_KEYBIT
, BTN_LEFT
);
62 ioctl(tablet
, UI_SET_KEYBIT
, BTN_MIDDLE
);
63 ioctl(tablet
, UI_SET_KEYBIT
, BTN_RIGHT
);
66 ioctl(tablet
, UI_SET_EVBIT
, EV_REL
);
67 ioctl(tablet
, UI_SET_RELBIT
, REL_WHEEL
);
70 ioctl(tablet
, UI_SET_EVBIT
, EV_ABS
);
71 ioctl(tablet
, UI_SET_ABSBIT
, ABS_X
);
72 ioctl(tablet
, UI_SET_ABSBIT
, ABS_Y
);
74 rc
= ioctl(tablet
, UI_DEV_CREATE
);
76 fprintf(stderr
, "%s: create error\n", __FUNCTION__
);
81 void uinput_close(void)
87 static void uinput_send_event(__u16 type
, __u16 code
, __s32 value
)
89 struct input_event event
= {
96 rc
= write(tablet
, &event
, sizeof(event
));
97 if (rc
!= sizeof(event
)) {
98 fprintf(stderr
, "%s: write error\n", __FUNCTION__
);
103 void uinput_do_mouse(VDAgentMouseState
*mouse
, int verbose
)
110 static const struct button_s btns
[] = {
111 { .name
= "left", .mask
= VD_AGENT_LBUTTON_MASK
, .btn
= BTN_LEFT
},
112 { .name
= "middle", .mask
= VD_AGENT_MBUTTON_MASK
, .btn
= BTN_MIDDLE
},
113 { .name
= "right", .mask
= VD_AGENT_RBUTTON_MASK
, .btn
= BTN_RIGHT
},
115 static const struct button_s wheel
[] = {
116 { .name
= "up", .mask
= VD_AGENT_UBUTTON_MASK
, .btn
= 1 },
117 { .name
= "down", .mask
= VD_AGENT_DBUTTON_MASK
, .btn
= -1 },
119 static VDAgentMouseState last
;
122 if (last
.x
!= mouse
->x
) {
124 fprintf(stderr
, "mouse: abs-x %d\n", mouse
->x
);
125 uinput_send_event(EV_ABS
, ABS_X
, mouse
->x
);
127 if (last
.y
!= mouse
->y
) {
129 fprintf(stderr
, "mouse: abs-y %d\n", mouse
->y
);
130 uinput_send_event(EV_ABS
, ABS_Y
, mouse
->y
);
132 for (i
= 0; i
< sizeof(btns
)/sizeof(btns
[0]); i
++) {
133 if ((last
.buttons
& btns
[i
].mask
) == (mouse
->buttons
& btns
[i
].mask
))
135 down
= !!(mouse
->buttons
& btns
[i
].mask
);
137 fprintf(stderr
, "mouse: btn-%s %s\n",
138 btns
[i
].name
, down
? "down" : "up");
139 uinput_send_event(EV_KEY
, btns
[i
].btn
, down
);
141 for (i
= 0; i
< sizeof(wheel
)/sizeof(wheel
[0]); i
++) {
142 if ((last
.buttons
& wheel
[i
].mask
) == (mouse
->buttons
& wheel
[i
].mask
))
144 if (mouse
->buttons
& wheel
[i
].mask
) {
146 fprintf(stderr
, "mouse: wheel-%s\n", wheel
[i
].name
);
147 uinput_send_event(EV_REL
, REL_WHEEL
, wheel
[i
].btn
);
151 fprintf(stderr
, "mouse: syn\n");
152 uinput_send_event(EV_SYN
, SYN_REPORT
, 0);