1 /*************************************************************************
2 Copyright (C) 2009 Matthew Thompson <chameleonator@gmail.com>
4 This file is part of libumd.
6 libumd is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 libumd is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with libumd. If not, see <http://www.gnu.org/licenses/>.
18 *************************************************************************/
21 #include "umd_private.h"
23 #if defined(__linux) || defined(linux)
27 #include <sys/types.h>
30 #include <linux/input.h>
31 #include <linux/uinput.h>
35 static struct uinput_user_dev uidev
;
36 static struct input_event event
;
38 static char *dev_filename
[] = {"/dev/uinput", "/dev/input/uinput", "/dev/misc/uinput", 0};
43 unsigned int events
[] = { EV_SYN
, EV_KEY
, EV_ABS
, EV_REL
, EV_MAX
};
44 unsigned int keys
[] = { BTN_MOUSE
, BTN_LEFT
, BTN_RIGHT
, BTN_MIDDLE
, KEY_MAX
};
45 unsigned int mouseabs
[] = { ABS_X
, ABS_Y
, ABS_MAX
};
46 unsigned int mouserel
[] = { REL_X
, REL_Y
, REL_MAX
};
48 for (i
=0; dev_filename
[i
] != 0; i
++) {
49 if ((fd
= open(dev_filename
[i
], O_WRONLY
)) >= 0)
55 case EACCES
: case EROFS
:
56 SET_ERROR("Could not open uinput device due to permissions");
58 case ENODEV
: case ENXIO
: case ENOTDIR
:
59 SET_ERROR("Could not find uinput device to open");
62 SET_ERROR("Could not open uinput device");
67 memset(&event
, 0, sizeof event
);
69 memset(&uidev
, 0, sizeof uidev
);
70 snprintf(uidev
.name
, UINPUT_MAX_NAME_SIZE
, "UMD Virtual Mouse (userspace driver)");
72 if (write(fd
, &uidev
, sizeof uidev
) != sizeof uidev
) {
73 SET_ERROR("Could not write to uinput device");
76 for (i
=0; events
[i
] != EV_MAX
; i
++) {
77 if (ioctl(fd
, UI_SET_EVBIT
, events
[i
]) < 0) {
78 SET_ERROR("Could not set up uinput device");
83 for (i
=0; keys
[i
] != KEY_MAX
; i
++) {
84 if (ioctl(fd
, UI_SET_KEYBIT
, keys
[i
]) < 0) {
85 SET_ERROR("Could not set up uinput device");
90 for (i
=0; mouseabs
[i
] != ABS_MAX
; i
++) {
91 if (ioctl(fd
, UI_SET_ABSBIT
, mouseabs
[i
]) < 0) {
92 SET_ERROR("Could not set up uinput device");
97 for (i
=0; mouserel
[i
] != REL_MAX
; i
++) {
98 if (ioctl(fd
, UI_SET_RELBIT
, mouserel
[i
]) < 0) {
99 SET_ERROR("Could not set up uinput device");
104 if (ioctl(fd
, UI_DEV_CREATE
, 0) < 0) {
105 SET_ERROR("Could not create uinput device");
110 usleep(500 * 1000); // TODO: replace this with something more sensible
118 SET_ERROR("Could not quit, umd was not initialized");
122 if (ioctl(fd
, UI_DEV_DESTROY
) != 0) {
123 SET_ERROR("Could not destroy virtual mouse device");
133 static int motion_event(unsigned int type
, int x
, int y
)
135 unsigned int code_x
, code_y
;
136 if (type
== EV_ABS
) {
145 gettimeofday(&event
.time
, NULL
);
150 if (write(fd
, &event
, sizeof event
) != sizeof event
)
156 if (write(fd
, &event
, sizeof event
) != sizeof event
)
160 event
.code
= SYN_REPORT
;
162 if (write(fd
, &event
, sizeof event
) != sizeof event
)
168 int UMD_Warp(int x
, int y
)
171 SET_ERROR("Could not warp mouse, umd was not initialized");
175 if (motion_event(EV_ABS
, x
, y
) < 0) {
176 SET_ERROR("Could not warp mouse");
183 int UMD_Move(int x
, int y
)
186 SET_ERROR("Could not move mouse, umd was not initialized");
190 if (motion_event(EV_REL
, x
, y
) < 0) {
191 SET_ERROR("Could not move mouse");
198 int UMD_Click(int button
, int state
)
213 SET_ERROR("Unrecognized mouse button in click");
217 gettimeofday(&event
.time
, NULL
);
222 if (write(fd
, &event
, sizeof event
) != sizeof event
)
226 event
.code
= SYN_REPORT
;
227 event
.value
= state
?1:0;
228 if (write(fd
, &event
, sizeof event
) != sizeof event
)
234 SET_ERROR("Could not set position of virtual device");
239 int UMD_ClickAt(int button
, int state
, int x
, int y
)
241 if (UMD_Warp(x
, y
) < 0)
244 if (UMD_Click(button
, state
) < 0)
250 int UMD_SingleClick(int button
)
252 if (UMD_Click(button
, 1) < 0)
255 if (UMD_Click(button
, 0) < 0)
261 int UMD_SingleClickAt(int button
, int x
, int y
)
263 if (UMD_ClickAt(button
, 1, x
, y
) < 0)
266 if (UMD_Click(button
, 0) < 0)