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 *************************************************************************/
24 /*************************************
26 *************************************/
27 #if defined(__linux) || defined(linux)
31 #include <sys/types.h>
34 #include <linux/input.h>
35 #include <linux/uinput.h>
38 /*************************************
40 *************************************/
41 #elif defined(_WIN32) || defined(__WIN32__)
43 #define _WIN32_WINNT 0x0500
46 /*************************************
48 *************************************/
49 #elif defined(__MACOSX__) || defined(__APPLE__)
52 # error This library does not support your platform!
56 static char error_buff
[ERROR_LEN
] = "";
58 #define SET_ERROR(message) \
59 { snprintf(error_buff, ERROR_LEN, "libumd error (%s:%d)\n\t%s", \
60 __FILE__, __LINE__ -1, message); }
62 const char *UMD_GetError()
67 /*************************************
69 *************************************/
70 #if defined(__linux) || defined(linux)
73 static struct uinput_user_dev uidev
;
74 static struct input_event event
;
76 static char *dev_filename
[] = {"/dev/uinput", "/dev/input/uinput", "/dev/misc/uinput", 0};
81 unsigned int events
[] = { EV_SYN
, EV_KEY
, EV_ABS
, EV_REL
, EV_MAX
};
82 unsigned int keys
[] = { BTN_MOUSE
, BTN_LEFT
, BTN_RIGHT
, BTN_MIDDLE
, KEY_MAX
};
83 unsigned int mouseabs
[] = { ABS_X
, ABS_Y
, ABS_MAX
};
84 unsigned int mouserel
[] = { REL_X
, REL_Y
, REL_MAX
};
86 for (i
=0; dev_filename
[i
] != 0; i
++) {
87 if ((fd
= open(dev_filename
[i
], O_WRONLY
)) >= 0)
93 case EACCES
: case EROFS
:
94 SET_ERROR("Could not open uinput device due to permissions");
96 case ENODEV
: case ENXIO
: case ENOTDIR
:
97 SET_ERROR("Could not find uinput device to open");
100 SET_ERROR("Could not open uinput device");
105 memset(&event
, 0, sizeof event
);
107 memset(&uidev
, 0, sizeof uidev
);
108 snprintf(uidev
.name
, UINPUT_MAX_NAME_SIZE
, "UMD Virtual Mouse (userspace driver)");
110 if (write(fd
, &uidev
, sizeof uidev
) != sizeof uidev
) {
111 SET_ERROR("Could not write to uinput device");
114 for (i
=0; events
[i
] != EV_MAX
; i
++) {
115 if (ioctl(fd
, UI_SET_EVBIT
, events
[i
]) < 0) {
116 SET_ERROR("Could not set up uinput device");
121 for (i
=0; keys
[i
] != KEY_MAX
; i
++) {
122 if (ioctl(fd
, UI_SET_KEYBIT
, keys
[i
]) < 0) {
123 SET_ERROR("Could not set up uinput device");
128 for (i
=0; mouseabs
[i
] != ABS_MAX
; i
++) {
129 if (ioctl(fd
, UI_SET_ABSBIT
, mouseabs
[i
]) < 0) {
130 SET_ERROR("Could not set up uinput device");
135 for (i
=0; mouserel
[i
] != REL_MAX
; i
++) {
136 if (ioctl(fd
, UI_SET_RELBIT
, mouserel
[i
]) < 0) {
137 SET_ERROR("Could not set up uinput device");
142 if (ioctl(fd
, UI_DEV_CREATE
, 0) < 0) {
143 SET_ERROR("Could not create uinput device");
148 usleep(500 * 1000); // TODO: replace this with something more sensible
156 SET_ERROR("Could not quit, umd was not initialized");
160 if (ioctl(fd
, UI_DEV_DESTROY
) != 0) {
161 SET_ERROR("Could not destroy virtual mouse device");
171 static int motion_event(unsigned int type
, int x
, int y
)
173 unsigned int code_x
, code_y
;
174 if (type
== EV_ABS
) {
183 gettimeofday(&event
.time
, NULL
);
188 if (write(fd
, &event
, sizeof event
) != sizeof event
)
194 if (write(fd
, &event
, sizeof event
) != sizeof event
)
198 event
.code
= SYN_REPORT
;
200 if (write(fd
, &event
, sizeof event
) != sizeof event
)
206 int UMD_Warp(int x
, int y
)
209 SET_ERROR("Could not warp mouse, umd was not initialized");
213 if (motion_event(EV_ABS
, x
, y
) < 0) {
214 SET_ERROR("Could not warp mouse");
221 int UMD_Move(int x
, int y
)
224 SET_ERROR("Could not move mouse, umd was not initialized");
228 if (motion_event(EV_REL
, x
, y
) < 0) {
229 SET_ERROR("Could not move mouse");
236 int UMD_Click(int button
, int state
)
251 SET_ERROR("Unrecognized mouse button in click");
255 gettimeofday(&event
.time
, NULL
);
260 if (write(fd
, &event
, sizeof event
) != sizeof event
)
264 event
.code
= SYN_REPORT
;
265 event
.value
= state
?1:0;
266 if (write(fd
, &event
, sizeof event
) != sizeof event
)
272 SET_ERROR("Could not set position of virtual device");
277 int UMD_ClickAt(int button
, int state
, int x
, int y
)
279 if (UMD_Warp(x
, y
) < 0)
282 if (UMD_Click(button
, state
) < 0)
288 int UMD_SingleClick(int button
)
290 if (UMD_Click(button
, 1) < 0)
293 if (UMD_Click(button
, 0) < 0)
299 int UMD_SingleClickAt(int button
, int x
, int y
)
301 if (UMD_ClickAt(button
, 1, x
, y
) < 0)
304 if (UMD_Click(button
, 0) < 0)
310 /*************************************
312 *************************************/
313 #elif defined(_WIN32) || defined(__WIN32__)
325 int UMD_Warp(int x
, int y
)
332 int UMD_Move(int x
, int y
)
336 if (GetCursorPos(&point
) == 0) {
337 SET_ERROR("Could not get current cursor position to move");
341 SetCursorPos(point
.x
+ x
, point
.y
+ y
);
346 static int get_flags(int button
, int state
)
352 flags
= state
? MOUSEEVENTF_LEFTDOWN
: MOUSEEVENTF_LEFTUP
;
355 flags
= state
? MOUSEEVENTF_RIGHTDOWN
: MOUSEEVENTF_RIGHTUP
;
358 flags
= state
? MOUSEEVENTF_MIDDLEDOWN
: MOUSEEVENTF_MIDDLEUP
;
361 SET_ERROR("Unrecognized mouse button in click");
368 int UMD_Click(int button
, int state
)
371 int flags
= get_flags(button
, state
);
376 memset(&input
, 0, sizeof input
);
377 input
.type
= INPUT_MOUSE
;
378 input
.mi
.dwFlags
= flags
;
380 if (SendInput(1, &input
, sizeof input
) != 1) {
381 SET_ERROR("Could not send click event");
388 int UMD_ClickAt(int button
, int state
, int x
, int y
)
391 int flags
= get_flags(button
, state
);
396 memset(&input
, 0, sizeof input
);
397 input
.type
= INPUT_MOUSE
;
398 input
.mi
.dwFlags
= flags
| MOUSEEVENTF_ABSOLUTE
| MOUSEEVENTF_MOVE
;
402 if (SendInput(1, &input
, sizeof input
) != 1) {
403 SET_ERROR("Could not send click at event");
410 int UMD_SingleClick(int button
)
412 if (UMD_Click(button
, 1) < 0)
415 if (UMD_Click(button
, 0) < 0)
421 int UMD_SingleClickAt(int button
, int x
, int y
)
423 if (UMD_ClickAt(button
, 1, x
, y
) < 0)
426 if (UMD_Click(button
, 0) < 0)
432 /*************************************
434 *************************************/
435 #elif defined(__MACOSX__) || defined(__APPLE__)