CRUX PPC
A lightweight GNU/Linux distribution for PowerPC!
Subversion Repository
Parent Directory
|
Revision Log
Revision 83 -
(show annotations)
Sun Oct 4 14:32:08 2009 UTC (3 years, 7 months ago) by cjg
File size: 23058 byte(s)
Sun Oct 4 14:32:08 2009 UTC (3 years, 7 months ago) by cjg
File size: 23058 byte(s)
mouseemu: added
| 1 | diff -ruN mouseemu-orig/Makefile mouseemu/Makefile |
| 2 | --- mouseemu-orig/Makefile 2005-03-30 08:48:19.000000000 +0200 |
| 3 | +++ mouseemu/Makefile 2008-11-23 12:14:26.000000000 +0100 |
| 4 | @@ -4,4 +4,4 @@ |
| 5 | rm -f *.o core* mouseemu |
| 6 | install: |
| 7 | cp -f mouseemu $(DESTDIR)/usr/sbin/ |
| 8 | - cp -f mouseemu.8 $(DESTDIR)/usr/man/man8 |
| 9 | + cp -f mouseemu.8 $(DESTDIR)/usr/share/man/man8 |
| 10 | diff -ruN mouseemu-orig/mouseemu.8 mouseemu/mouseemu.8 |
| 11 | --- mouseemu-orig/mouseemu.8 2005-03-30 08:46:20.000000000 +0200 |
| 12 | +++ mouseemu/mouseemu.8 2008-11-23 12:14:26.000000000 +0100 |
| 13 | @@ -30,23 +30,61 @@ |
| 14 | .SH OPTIONS |
| 15 | .TP |
| 16 | .B -middle B2_MOD B2_KEY |
| 17 | -modifier and key for the middle (second) mouse button |
| 18 | +Modifier and key for the middle (second) mouse button. Defaults to F10 and no modifier |
| 19 | +on PowerPC and Intel Macs, and to none on all other architectures. |
| 20 | .TP |
| 21 | .B -right B3_MOD B3_KEY |
| 22 | -modifier and key for the right (third) mouse button |
| 23 | +Modifier and key for the right (third) mouse button. Defaults to F11 and no modifier |
| 24 | +on PowerPC and Intel Macs, and to none on all other architectures. |
| 25 | .TP |
| 26 | .B -scroll SCROLL_MOD |
| 27 | -modifier for the scrolling function |
| 28 | +Modifier for the scrolling function. Defaults to Alt. |
| 29 | .TP |
| 30 | .B -typing-block DELAY |
| 31 | Time in milliseconds for which the trackpad will be blocked while typing on the keyboard. |
| 32 | +Defaults to 300ms. |
| 33 | .TP |
| 34 | .B -device UINPUT |
| 35 | -device node for the uinput device |
| 36 | +Device node for the uinput device. Defaults to /dev/uinput. If this device is not read and |
| 37 | +writeable the following devices are also tried: /dev/uinput, /dev/input/uinput and |
| 38 | +/dev/misc/uinput. |
| 39 | .TP |
| 40 | .B -nofork |
| 41 | don't run in the background |
| 42 | - |
| 43 | +.TP |
| 44 | +.B -autorescan |
| 45 | +Automatically scan every 5s for new devices. This is normally not need, as udev should |
| 46 | +inform mouseemu about new devices. |
| 47 | +.TP |
| 48 | +.B -debug |
| 49 | +print debugging messages about device scans |
| 50 | +.TP |
| 51 | +.B -help |
| 52 | +show usage message |
| 53 | +.PP |
| 54 | +The key codes for the buttons and modifiers are key scancodes. They can be found in |
| 55 | +include/linux/input.h in the kernel headers or by using `showkey` in a console. The |
| 56 | +keycodes must be given as decimal values (`showkey` displays hex values!). |
| 57 | +.PP |
| 58 | +Mouseemu does normally not automatically scan for new devices. An udev rule is used |
| 59 | +to trigger a rescan when new devices are connected. You can also trigger a rescan |
| 60 | +manually by sending a HUP signal to the mouseemu process. |
| 61 | +.SH EXAMPLES |
| 62 | +.PP |
| 63 | +To have the same behaviour as in MacOS X (CTRL-click for right mouse button and no |
| 64 | +emulation for the middle button): |
| 65 | +.PP |
| 66 | +.RS 4 |
| 67 | +.B mouseemu -middle 0 0 -right 29 272 |
| 68 | +.RE |
| 69 | +.PP |
| 70 | +The code for the (left) mouse button is 272 (0x110 in hex). The code for CTRL is 29. |
| 71 | +.PP |
| 72 | +Trigger a rescan for newly attached devices: |
| 73 | +.PP |
| 74 | +.RS 4 |
| 75 | +.B kill -HUP `cat /var/run/mouseemu.pid` |
| 76 | +.RE |
| 77 | .SH AUTHOR |
| 78 | Mouseemu was written by Colin Leroy |
| 79 | .nh |
| 80 | diff -ruN mouseemu-orig/mouseemu.c mouseemu/mouseemu.c |
| 81 | --- mouseemu-orig/mouseemu.c 2005-03-30 08:40:30.000000000 +0200 |
| 82 | +++ mouseemu/mouseemu.c 2008-11-23 12:14:26.000000000 +0100 |
| 83 | @@ -18,17 +18,27 @@ |
| 84 | |
| 85 | #include <stdio.h> |
| 86 | #include <stdlib.h> |
| 87 | +#include <stdarg.h> |
| 88 | #include <unistd.h> |
| 89 | +#include <errno.h> |
| 90 | #include <fcntl.h> |
| 91 | #include <string.h> |
| 92 | #include <signal.h> |
| 93 | #include <wait.h> |
| 94 | +#include <syslog.h> |
| 95 | #include <sys/time.h> |
| 96 | +#include <sys/types.h> |
| 97 | +#include <sys/stat.h> |
| 98 | #include <linux/input.h> |
| 99 | +#ifndef BUS_VIRTUAL /* new in Linux 2.6.19 */ |
| 100 | +#define BUS_VIRTUAL 0x06 |
| 101 | +#endif |
| 102 | #include <linux/uinput.h> |
| 103 | #include "mouseemu.h" |
| 104 | #include "defkeys.h" |
| 105 | |
| 106 | +static int use_defaults = 0; |
| 107 | + |
| 108 | static int b2_mod = BUTTON2MOD; |
| 109 | static int b2_key = BUTTON2KEY; |
| 110 | |
| 111 | @@ -47,12 +57,25 @@ |
| 112 | |
| 113 | static int running = -1; |
| 114 | volatile sig_atomic_t answer = 1; |
| 115 | +volatile sig_atomic_t rescan = 0; |
| 116 | pid_t pid = -1; |
| 117 | -#define EVENT_DEVS 6 |
| 118 | +#define EVENT_DEVS 32 |
| 119 | static kdev eventdevs[EVENT_DEVS]; |
| 120 | static input_handler ihandler[EVENT_DEVS]; |
| 121 | |
| 122 | +static int debug = 0; |
| 123 | +static int autorescan = 0; |
| 124 | |
| 125 | +/* print debug messages to syslog or stderr */ |
| 126 | +void debugf(const char *format, ...) { |
| 127 | + va_list ap; |
| 128 | + |
| 129 | + if (debug) { |
| 130 | + va_start(ap, format); |
| 131 | + vsyslog(LOG_DEBUG, format, ap); |
| 132 | + va_end(ap); |
| 133 | + } |
| 134 | +} |
| 135 | |
| 136 | static void send_event(int fd, int type, int code, int value) |
| 137 | { |
| 138 | @@ -72,7 +95,7 @@ |
| 139 | |
| 140 | static void passthrough(int fd, struct input_event event) |
| 141 | { |
| 142 | - if (write(fd, &event, sizeof(event)) < sizeof(event)) |
| 143 | + if (write(fd, &event, sizeof(event)) <= 0) |
| 144 | perror("passthrough error"); |
| 145 | |
| 146 | } |
| 147 | @@ -164,52 +187,66 @@ |
| 148 | } |
| 149 | } |
| 150 | |
| 151 | -void keyboard_handler (int fd) |
| 152 | +void keyboard_handler (struct input_event inp) |
| 153 | { |
| 154 | - struct input_event inp; |
| 155 | - if (read(fd, &inp, sizeof(inp)) == sizeof(inp)) { |
| 156 | - if (!event_parse(inp.code, inp.value) && !is_modifier(inp)) { |
| 157 | - last_key = (inp.time.tv_sec*1000000 + inp.time.tv_usec); |
| 158 | - } |
| 159 | + if (inp.type != EV_KEY && inp.type != EV_REP) |
| 160 | + return; |
| 161 | + if (inp.type == EV_KEY && (inp.code == BTN_LEFT || inp.code == BTN_MIDDLE || inp.code == BTN_RIGHT)) |
| 162 | + return; |
| 163 | + |
| 164 | + if (!event_parse(inp.code, inp.value) && !is_modifier(inp)) { |
| 165 | + last_key = (inp.time.tv_sec*1000000 + inp.time.tv_usec); |
| 166 | + } |
| 167 | /* I think its best not to pass scroll, or experiment with not passing the release if |
| 168 | * we actually used it for scrolling (but some apps may get stuck?) |
| 169 | */ |
| 170 | - if (inp.code != b2_key && inp.code != b3_key && !b2_mod_pressed && !b3_mod_pressed) { |
| 171 | - passthrough(ui_keyb_fd, inp); |
| 172 | - } |
| 173 | + if (inp.code != b2_key && inp.code != b3_key) { |
| 174 | + passthrough(ui_keyb_fd, inp); |
| 175 | + } |
| 176 | +} |
| 177 | + |
| 178 | +static void mouse_handler (struct input_event inp) |
| 179 | +{ |
| 180 | + if (inp.type != EV_KEY && inp.type != EV_REL && inp.type != EV_SYN) |
| 181 | + return; |
| 182 | + if (inp.type == EV_KEY && inp.code != BTN_LEFT && inp.code != BTN_MIDDLE && inp.code != BTN_RIGHT) |
| 183 | + return; |
| 184 | + |
| 185 | + if (inp.type == EV_KEY && inp.code == BTN_LEFT) { |
| 186 | + if (b2_key == BTN_LEFT && b2_mod_pressed) |
| 187 | + report_click(BTN_MIDDLE, inp.value); |
| 188 | + else if (b3_key == BTN_LEFT && b3_mod_pressed) |
| 189 | + report_click(BTN_RIGHT, inp.value); |
| 190 | + else |
| 191 | + passthrough(ui_mouse_fd, inp); |
| 192 | + } |
| 193 | + else if (scroll_mod_pressed |
| 194 | + && inp.type == EV_REL |
| 195 | + && (inp.code == REL_Y || inp.code == REL_X)) { |
| 196 | + report_scroll (inp.value); |
| 197 | + //printf("inp.value %d\n", inp.value); |
| 198 | + } else { |
| 199 | + if ((inp.time.tv_sec*1000000+inp.time.tv_usec)-last_key > typing_block_delay*1000 |
| 200 | + || inp.type == EV_REL) |
| 201 | + passthrough(ui_mouse_fd, inp); |
| 202 | } |
| 203 | } |
| 204 | |
| 205 | -static void mouse_handler (int fd) |
| 206 | +static void event_handler (int mode, int fd) |
| 207 | { |
| 208 | - int count; |
| 209 | struct input_event inp; |
| 210 | |
| 211 | - if ((count = read(fd, &inp, sizeof(inp))) == sizeof(inp)) { |
| 212 | - if (inp.type == EV_KEY && inp.code == BTN_LEFT) { |
| 213 | - if (b2_key == BTN_LEFT && b2_mod_pressed) |
| 214 | - report_click(BTN_MIDDLE, inp.value); |
| 215 | - else if (b3_key == BTN_LEFT && b3_mod_pressed) |
| 216 | - report_click(BTN_RIGHT, inp.value); |
| 217 | - else |
| 218 | - passthrough(ui_mouse_fd, inp); |
| 219 | - } |
| 220 | - else if (scroll_mod_pressed |
| 221 | - && inp.type == EV_REL |
| 222 | - && (inp.code == REL_Y || inp.code == REL_X)) { |
| 223 | - report_scroll (inp.value); |
| 224 | - //printf("inp.value %d\n", inp.value); |
| 225 | - } else { |
| 226 | - if ((inp.time.tv_sec*1000000+inp.time.tv_usec)-last_key > typing_block_delay*1000 |
| 227 | - || inp.type == EV_REL) |
| 228 | - passthrough(ui_mouse_fd, inp); |
| 229 | - } |
| 230 | + if (read(fd, &inp, sizeof(inp)) == sizeof(inp)) { |
| 231 | + if (mode & HANDLER_KEYBOARD) |
| 232 | + keyboard_handler(inp); |
| 233 | + if (mode & HANDLER_MOUSE) |
| 234 | + mouse_handler(inp); |
| 235 | } |
| 236 | } |
| 237 | |
| 238 | void scan_for_devs() |
| 239 | { |
| 240 | - int n, m, fd; |
| 241 | + int n, m, fd, mode; |
| 242 | char filename[20]; |
| 243 | unsigned long bit[NBITS(EV_MAX)]; |
| 244 | unsigned short id[EVENT_DEVS]; |
| 245 | @@ -217,23 +254,34 @@ |
| 246 | for (n = 0, m = 0; n < EVENT_DEVS; n++) { |
| 247 | sprintf(filename, "/dev/input/event%d", n); |
| 248 | if ((fd = open(filename, O_RDONLY)) >= 0) { |
| 249 | + mode = 0; |
| 250 | ioctl(fd, EVIOCGBIT(0, EV_MAX), bit); |
| 251 | + ioctl(fd, EVIOCGID, id); |
| 252 | if (test_bit(EV_KEY, bit) && test_bit(EV_REP, bit)) { |
| 253 | - ioctl(fd, EVIOCGID, id); |
| 254 | + /* our own virtual keyboard (on rescans)*/ |
| 255 | + if (id[ID_PRODUCT] == 0x1F && id[ID_VENDOR] == 0x1F) { |
| 256 | + close(fd); |
| 257 | + continue; |
| 258 | + } |
| 259 | + mode |= HANDLER_KEYBOARD; |
| 260 | if (id[ID_PRODUCT] != eventdevs[m].product || |
| 261 | id[ID_VENDOR] != eventdevs[m].vendor) { |
| 262 | - if (eventdevs[m].handle >= 0) { |
| 263 | - unregister_inputhandler(eventdevs[m].handle); |
| 264 | - close(eventdevs[m].handle); |
| 265 | - } |
| 266 | - eventdevs[m].handle= fd; |
| 267 | - eventdevs[m].product = id[ID_PRODUCT]; |
| 268 | - eventdevs[m].vendor = id[ID_VENDOR]; |
| 269 | - register_inputhandler(fd, keyboard_handler, 1); |
| 270 | + debugf("keyboard: fd %d event%d, vendor %4x product %4x\n", fd, n, id[ID_VENDOR], id[ID_PRODUCT]); |
| 271 | } |
| 272 | - m++; |
| 273 | - } else if (test_bit(EV_REL, bit)) { |
| 274 | - ioctl(fd, EVIOCGID, id); |
| 275 | + } |
| 276 | + if (test_bit(EV_REL, bit)) { |
| 277 | + /* our own virtual mouse (on rescans)*/ |
| 278 | + if (id[ID_PRODUCT] == 0x1E && id[ID_VENDOR] == 0x1F) { |
| 279 | + close(fd); |
| 280 | + continue; |
| 281 | + } |
| 282 | + mode |= HANDLER_MOUSE; |
| 283 | + if (id[ID_PRODUCT] != eventdevs[m].product || |
| 284 | + id[ID_VENDOR] != eventdevs[m].vendor) { |
| 285 | + debugf("mouse : fd %d event%d, vendor %4x product %4x\n", fd, n, id[ID_VENDOR], id[ID_PRODUCT]); |
| 286 | + } |
| 287 | + } |
| 288 | + if (mode) { |
| 289 | if (id[ID_PRODUCT] != eventdevs[m].product || |
| 290 | id[ID_VENDOR] != eventdevs[m].vendor) { |
| 291 | if (eventdevs[m].handle >= 0) { |
| 292 | @@ -243,9 +291,10 @@ |
| 293 | eventdevs[m].handle= fd; |
| 294 | eventdevs[m].product = id[ID_PRODUCT]; |
| 295 | eventdevs[m].vendor = id[ID_VENDOR]; |
| 296 | - register_inputhandler(fd, mouse_handler, 1); |
| 297 | - } |
| 298 | - m++; |
| 299 | + register_inputhandler(mode, fd, event_handler, 1); |
| 300 | + } else |
| 301 | + close(fd); |
| 302 | + m++; |
| 303 | } else |
| 304 | close(fd); |
| 305 | } |
| 306 | @@ -257,12 +306,34 @@ |
| 307 | } |
| 308 | } |
| 309 | |
| 310 | -int register_inputhandler (int fd, void (*func)(int fd), int grab) |
| 311 | +void rescan_devs() |
| 312 | +{ |
| 313 | + int i, cfd; |
| 314 | + |
| 315 | + for (i=0; i<EVENT_DEVS; i++) { |
| 316 | + if (ihandler[i].fd != -1) { |
| 317 | + cfd=ihandler[i].fd; |
| 318 | + unregister_inputhandler(ihandler[i].fd); |
| 319 | + close(cfd); |
| 320 | + i--; |
| 321 | + } |
| 322 | + } |
| 323 | + for (i=0; i<EVENT_DEVS; i++) { |
| 324 | + eventdevs[i].product = 0; |
| 325 | + eventdevs[i].vendor = 0; |
| 326 | + eventdevs[i].handle = -1; |
| 327 | + } |
| 328 | + usleep(100); |
| 329 | + scan_for_devs(); |
| 330 | +} |
| 331 | + |
| 332 | +int register_inputhandler (int mode, int fd, void (*func)(int mode, int fd), int grab) |
| 333 | { |
| 334 | int n; |
| 335 | |
| 336 | for (n=0; n < EVENT_DEVS; n++) |
| 337 | if (ihandler[n].fd == -1) { |
| 338 | + ihandler[n].mode = mode; |
| 339 | ihandler[n].fd = fd; |
| 340 | ihandler[n].handler = func; |
| 341 | ihandler[n].grab = grab; |
| 342 | @@ -279,6 +350,7 @@ |
| 343 | |
| 344 | for (n = 0; n < EVENT_DEVS; n++) |
| 345 | if (found) { |
| 346 | + ihandler[n-1].mode = ihandler[n].mode; |
| 347 | ihandler[n-1].fd = ihandler[n].fd; |
| 348 | ihandler[n-1].handler = ihandler[n].handler; |
| 349 | } else if (ihandler[n].fd == fd) { |
| 350 | @@ -296,7 +368,7 @@ |
| 351 | |
| 352 | FD_ZERO(watchset); |
| 353 | for (maxfd=n=0; n < EVENT_DEVS; n++) { |
| 354 | - if (ihandler[n].fd == -1) break; |
| 355 | + if (ihandler[n].fd == -1) continue; |
| 356 | FD_SET(ihandler[n].fd, watchset); |
| 357 | if (ihandler[n].fd > maxfd) |
| 358 | maxfd = ihandler[n].fd; |
| 359 | @@ -309,9 +381,9 @@ |
| 360 | int n; |
| 361 | |
| 362 | for (n=0; n < EVENT_DEVS; n++) { |
| 363 | - if (ihandler[n].fd == -1) break; |
| 364 | + if (ihandler[n].fd == -1) continue; |
| 365 | if (FD_ISSET(ihandler[n].fd, inset)) |
| 366 | - ihandler[n].handler (ihandler[n].fd); |
| 367 | + ihandler[n].handler (ihandler[n].mode, ihandler[n].fd); |
| 368 | } |
| 369 | } |
| 370 | |
| 371 | @@ -333,27 +405,27 @@ |
| 372 | { |
| 373 | int fd = -1; |
| 374 | |
| 375 | - printf("Trying to open %s...", uinputdev); |
| 376 | + syslog(LOG_NOTICE, "Trying to open %s...", uinputdev); |
| 377 | fd = open (uinputdev, O_RDWR); |
| 378 | - printf(" %s.\n", (fd > 0)?"ok":"error"); |
| 379 | + syslog(LOG_NOTICE, " %s.\n", (fd > 0)?"ok":"error"); |
| 380 | if (fd > 0) |
| 381 | return fd; |
| 382 | |
| 383 | - printf("Trying to open /dev/uinput..."); |
| 384 | + syslog(LOG_NOTICE, "Trying to open /dev/uinput..."); |
| 385 | fd = open("/dev/uinput", O_RDWR); |
| 386 | - printf(" %s.\n", (fd > 0)?"ok":"error"); |
| 387 | + syslog(LOG_NOTICE, " %s.\n", (fd > 0)?"ok":"error"); |
| 388 | if (fd > 0) |
| 389 | return fd; |
| 390 | |
| 391 | - printf("Trying to open /dev/input/uinput..."); |
| 392 | + syslog(LOG_NOTICE, "Trying to open /dev/input/uinput..."); |
| 393 | fd = open("/dev/input/uinput", O_RDWR); |
| 394 | - printf(" %s.\n", (fd > 0)?"ok":"error"); |
| 395 | + syslog(LOG_NOTICE, " %s.\n", (fd > 0)?"ok":"error"); |
| 396 | if (fd > 0) |
| 397 | return fd; |
| 398 | |
| 399 | - printf("Trying to open /dev/misc/uinput..."); |
| 400 | + syslog(LOG_NOTICE, "Trying to open /dev/misc/uinput..."); |
| 401 | fd = open("/dev/misc/uinput", O_RDWR); |
| 402 | - printf(" %s.\n", (fd > 0)?"ok":"error"); |
| 403 | + syslog(LOG_NOTICE, " %s.\n", (fd > 0)?"ok":"error"); |
| 404 | if (fd > 0) |
| 405 | return fd; |
| 406 | |
| 407 | @@ -365,6 +437,7 @@ |
| 408 | struct uinput_user_dev device; |
| 409 | int i; |
| 410 | |
| 411 | + memset(&device, 0, sizeof(struct uinput_user_dev)); |
| 412 | /*setup keyboard device */ |
| 413 | |
| 414 | if(ui_keyb_fd > 0) { |
| 415 | @@ -380,7 +453,7 @@ |
| 416 | |
| 417 | strcpy(device.name, "Mouseemu virtual keyboard"); |
| 418 | |
| 419 | - device.id.bustype = 0; |
| 420 | + device.id.bustype = BUS_VIRTUAL; |
| 421 | device.id.vendor = 0x1F; |
| 422 | device.id.product = 0x1F; |
| 423 | device.id.version = 0; |
| 424 | @@ -422,7 +495,7 @@ |
| 425 | |
| 426 | strcpy(device.name, "Mouseemu virtual mouse"); |
| 427 | |
| 428 | - device.id.bustype = 0; |
| 429 | + device.id.bustype = BUS_VIRTUAL; |
| 430 | device.id.vendor = 0x1F; |
| 431 | device.id.product = 0x1E; |
| 432 | device.id.version = 0; |
| 433 | @@ -457,17 +530,18 @@ |
| 434 | |
| 435 | void uinput_cleanup() |
| 436 | { |
| 437 | - int i; |
| 438 | + int i, cfd; |
| 439 | |
| 440 | - printf("mouseemu: cleaning...\n"); |
| 441 | + syslog(LOG_NOTICE, "mouseemu: cleaning...\n"); |
| 442 | |
| 443 | uinput_close(ui_keyb_fd); |
| 444 | uinput_close(ui_mouse_fd); |
| 445 | |
| 446 | for (i=0; i<EVENT_DEVS; i++) { |
| 447 | if (ihandler[i].fd != -1) { |
| 448 | + cfd=ihandler[i].fd; |
| 449 | unregister_inputhandler(ihandler[i].fd); |
| 450 | - close(ihandler[i].fd); |
| 451 | + close(cfd); |
| 452 | } |
| 453 | } |
| 454 | |
| 455 | @@ -485,6 +559,11 @@ |
| 456 | { |
| 457 | if (sig_num == SIGUSR1) { |
| 458 | answer = 1; |
| 459 | + } else if (sig_num == SIGHUP) { |
| 460 | + rescan = 1; |
| 461 | + } else if (sig_num == SIGALRM) { |
| 462 | + rescan = 1; |
| 463 | + alarm(5); |
| 464 | } else { |
| 465 | //printf("mouseemu: aborting on sig %i \n",sig_num); |
| 466 | /*terminate the parent:*/ |
| 467 | @@ -508,15 +587,51 @@ |
| 468 | |
| 469 | /*SIGUSR1 for process communication |
| 470 | *SIGTERM and SIGCHLD for quitting |
| 471 | + *SIGHUP and SIGALRM for rescaning devices |
| 472 | */ |
| 473 | sigaction(SIGUSR1, &usr_action, NULL); |
| 474 | sigaction(SIGTERM, &usr_action, NULL); |
| 475 | + sigaction(SIGHUP, &usr_action, NULL); |
| 476 | sigaction(SIGCHLD, &usr_action, NULL); |
| 477 | + sigaction(SIGALRM, &usr_action, NULL); |
| 478 | |
| 479 | sigprocmask(SIG_UNBLOCK, &mask, 0); |
| 480 | |
| 481 | } |
| 482 | |
| 483 | +/* print usage message to stdout/stderr */ |
| 484 | +void usage(FILE *stream, char *argv[]) { |
| 485 | + fprintf(stream, "usage: %s \n" |
| 486 | + "\t[-middle B2_MOD B2_KEY]\n" |
| 487 | + "\t[-right B3_MOD B3_KEY]\n" |
| 488 | + "\t[-scroll SCROLL_MOD]\n" |
| 489 | + "\t[-typing-block DELAY]\n" |
| 490 | + "\t[-device UINPUT_DEVICE]\n" |
| 491 | + "\t[-nofork]\n" |
| 492 | + "\t[-autorescan]\n" |
| 493 | + "\t[-debug]\n", |
| 494 | + argv[0]); |
| 495 | + fprintf(stream, "All modifier and button key arguments are\n" |
| 496 | + "key scancodes. They can be found in \n" |
| 497 | + "/usr/src/linux/include/linux/input.h,\n" |
| 498 | + "or by using `showkey` in a console.\n" |
| 499 | + "Use decimal values. BTN_LEFT(272) is usable as " |
| 500 | + "B2_KEY or B3_KEY.\n\n"); |
| 501 | + fprintf(stream, "Default uinput device: " DEFAULT_UINPUT ".\n"); |
| 502 | + fprintf(stream, "Default keys:\n"); |
| 503 | + if (use_defaults) |
| 504 | + fprintf(stream, |
| 505 | + "\tMiddle click : F10 (0 68)\n" |
| 506 | + "\tRight click : F11 (0 87)\n"); |
| 507 | + else |
| 508 | + fprintf(stream, |
| 509 | + "\tMiddle click : none (0 0)\n" |
| 510 | + "\tRight click : none (0 0)\n"); |
| 511 | + fprintf(stream, "\tScroll mod. : Alt (56)\n" |
| 512 | + "\tDefault blocking time while typing: 300ms\n"); |
| 513 | + |
| 514 | + exit(0); |
| 515 | +} |
| 516 | |
| 517 | int main(int argc, char *argv[]) |
| 518 | { |
| 519 | @@ -527,94 +642,117 @@ |
| 520 | int nofork = 0; |
| 521 | //int argv0size = strlen(argv[0]); |
| 522 | |
| 523 | - printf("mouseemu " VERSION " (C) Colin Leroy <colin@colino.net>\n"); |
| 524 | - |
| 525 | install_sighandler(); |
| 526 | |
| 527 | +#ifdef __powerpc__ |
| 528 | + use_defaults = 1; |
| 529 | +#else |
| 530 | +#if defined(__i386__) || defined(__amd64__) |
| 531 | + { |
| 532 | + FILE *dmidecode; |
| 533 | + char line[1024]; |
| 534 | + dmidecode = popen("dmidecode -s system-manufacturer 2>/dev/null", "r"); |
| 535 | + if (dmidecode) { |
| 536 | + if (fgets(line, 1024, dmidecode) && !strncmp(line, "Apple", 5)) |
| 537 | + use_defaults = 1; |
| 538 | + pclose(dmidecode); |
| 539 | + } |
| 540 | + } |
| 541 | +#endif |
| 542 | +#endif |
| 543 | + if (!use_defaults) { |
| 544 | + b2_mod = 0; |
| 545 | + b2_key = 0; |
| 546 | + b3_mod = 0; |
| 547 | + b3_key = 0; |
| 548 | + } |
| 549 | + |
| 550 | uinputdev = DEFAULT_UINPUT; |
| 551 | if (argc > 1) { |
| 552 | int i = 0; |
| 553 | if (!strcmp(argv[1],"-help")) { |
| 554 | -err: |
| 555 | - printf("usage: %s \n" |
| 556 | - "\t[-middle B2_MOD B2_KEY]\n" |
| 557 | - "\t[-right B3_MOD B3_KEY]\n" |
| 558 | - "\t[-scroll SCROLL_MOD]\n" |
| 559 | - "\t[-typing-block DELAY]\n" |
| 560 | - "\t[-device UINPUT_DEVICE]\n" |
| 561 | - "\t[-nofork]\n", |
| 562 | - argv[0]); |
| 563 | - printf("Key codes can be found in " |
| 564 | - "/usr/src/linux/include/linux/input.h,\n" |
| 565 | - "or by using `showkey` in console.\n" |
| 566 | - "Use decimal values. BTN_LEFT(272) is usable as " |
| 567 | - "B2_KEY or B3_KEY.\n\n"); |
| 568 | - printf("Default uinput device: " DEFAULT_UINPUT ".\n"); |
| 569 | - printf("Default keys:\n" |
| 570 | - "\tMiddle click : F10 (0 68)\n" |
| 571 | - "\tRight click : F11 (0 87)\n" |
| 572 | - "\tScroll mod. : Alt (56)\n" |
| 573 | - "\tDefault blocking time while typing: 300ms\n"); |
| 574 | - |
| 575 | - exit(0); |
| 576 | + usage(stdout, argv); |
| 577 | } else { |
| 578 | - for (i = 1; i < argc; i++) { |
| 579 | - int j = i+1; |
| 580 | + i = 1; |
| 581 | + while (i < argc) { |
| 582 | if (!strcmp(argv[i], "-middle")) { |
| 583 | - if (argc > j+1) { |
| 584 | - b2_mod = atoi(argv[j]); |
| 585 | - b2_key = atoi(argv[j+1]); |
| 586 | + if (argc > i+2) { |
| 587 | + b2_mod = atoi(argv[i+1]); |
| 588 | + b2_key = atoi(argv[i+2]); |
| 589 | + i += 3; |
| 590 | } else |
| 591 | - goto err; |
| 592 | + usage(stderr, argv); |
| 593 | continue; |
| 594 | } |
| 595 | - if (!strcmp(argv[i], "-right")) { |
| 596 | - if (argc > j+1) { |
| 597 | - b3_mod = atoi(argv[j]); |
| 598 | - b3_key = atoi(argv[j+1]); |
| 599 | + else if (!strcmp(argv[i], "-right")) { |
| 600 | + if (argc > i+2) { |
| 601 | + b3_mod = atoi(argv[i+1]); |
| 602 | + b3_key = atoi(argv[i+2]); |
| 603 | + i += 3; |
| 604 | } else |
| 605 | - goto err; |
| 606 | + usage(stderr, argv); |
| 607 | continue; |
| 608 | } |
| 609 | - if (!strcmp(argv[i], "-scroll")) { |
| 610 | - if (argc > j) { |
| 611 | - scroll_mod = atoi(argv[j]); |
| 612 | + else if (!strcmp(argv[i], "-scroll")) { |
| 613 | + if (argc > i+1) { |
| 614 | + scroll_mod = atoi(argv[i+1]); |
| 615 | + i += 2; |
| 616 | } else |
| 617 | - goto err; |
| 618 | + usage(stderr, argv); |
| 619 | continue; |
| 620 | } |
| 621 | - if (!strcmp(argv[i], "-typing-block")) { |
| 622 | - if (argc > j) { |
| 623 | - typing_block_delay = atoi(argv[j]); |
| 624 | + else if (!strcmp(argv[i], "-typing-block")) { |
| 625 | + if (argc > i+1) { |
| 626 | + typing_block_delay = atoi(argv[i+1]); |
| 627 | + i += 2; |
| 628 | } else |
| 629 | - goto err; |
| 630 | + usage(stderr, argv); |
| 631 | continue; |
| 632 | } |
| 633 | - if (!strcmp(argv[i], "-device")) { |
| 634 | - if (argc > j) { |
| 635 | - uinputdev = argv[j]; |
| 636 | + else if (!strcmp(argv[i], "-device")) { |
| 637 | + if (argc > i+1) { |
| 638 | + uinputdev = argv[i+1]; |
| 639 | + i += 2; |
| 640 | } else |
| 641 | - goto err; |
| 642 | + usage(stderr, argv); |
| 643 | continue; |
| 644 | } |
| 645 | - if (!strcmp(argv[i], "-nofork")) { |
| 646 | + else if (!strcmp(argv[i], "-nofork")) { |
| 647 | nofork=1; |
| 648 | + i += 1; |
| 649 | + continue; |
| 650 | + } |
| 651 | + else if (!strcmp(argv[i], "-autorescan")) { |
| 652 | + autorescan=1; |
| 653 | + i += 1; |
| 654 | continue; |
| 655 | } |
| 656 | + else if (!strcmp(argv[i], "-debug")) { |
| 657 | + debug=1; |
| 658 | + i += 1; |
| 659 | + continue; |
| 660 | + } else { |
| 661 | + usage(stderr, argv); |
| 662 | + } |
| 663 | } |
| 664 | } |
| 665 | } |
| 666 | - printf("using (%d+%d) as middle button, (%d+%d) as right button, (%d) as scroll.\n", |
| 667 | + |
| 668 | + if (nofork) |
| 669 | + openlog("mouseemu", LOG_NDELAY | LOG_PERROR | LOG_PID, LOG_DAEMON); |
| 670 | + else |
| 671 | + openlog("mouseemu", LOG_NDELAY | LOG_PID, LOG_DAEMON); |
| 672 | + |
| 673 | + syslog(LOG_NOTICE, "mouseemu " VERSION " (C) Colin Leroy <colin@colino.net>\n"); |
| 674 | + syslog(LOG_NOTICE, "using (%d+%d) as middle button, (%d+%d) as right button, (%d) as scroll.\n", |
| 675 | b2_mod, b2_key, b3_mod, b3_key, scroll_mod); |
| 676 | - printf("using %s.\n", uinputdev); |
| 677 | |
| 678 | - |
| 679 | if (nofork) |
| 680 | goto startops; |
| 681 | |
| 682 | fpid = fork(); |
| 683 | if (fpid == -1) { |
| 684 | - printf("can't fork\n"); |
| 685 | + syslog(LOG_NOTICE, "can't fork\n"); |
| 686 | goto startops; |
| 687 | } |
| 688 | if (fpid != 0) { |
| 689 | @@ -624,7 +762,7 @@ |
| 690 | setsid(); |
| 691 | pid = fork(); |
| 692 | if (pid == -1) { |
| 693 | - printf("can't fork\n"); |
| 694 | + syslog(LOG_NOTICE, "can't fork\n"); |
| 695 | goto startops; |
| 696 | } |
| 697 | |
| 698 | @@ -635,8 +773,25 @@ |
| 699 | * |
| 700 | */ |
| 701 | |
| 702 | + struct sigaction sa; |
| 703 | sigset_t mask, oldmask; |
| 704 | + FILE *pidfile; |
| 705 | |
| 706 | + /* SIGHUP and SIGALRM are only useful in the child */ |
| 707 | + memset(&sa, 0, sizeof(sa)); |
| 708 | + sa.sa_handler = SIG_IGN; |
| 709 | + sigaction(SIGHUP, &sa, NULL); |
| 710 | + sigaction(SIGALRM, &sa, NULL); |
| 711 | + |
| 712 | + /* write PID file so the user can signal us for device rescans */ |
| 713 | + pidfile = fopen("/var/run/mouseemu.pid", "w"); |
| 714 | + if (!pidfile) { |
| 715 | + perror("mouseemu: can't open /var/run/mouseemu.pid"); |
| 716 | + exit(1); |
| 717 | + } |
| 718 | + fprintf(pidfile, "%d\n", pid); |
| 719 | + fclose(pidfile); |
| 720 | + |
| 721 | /*we start only after we received the first sigusr1 from child:*/ |
| 722 | |
| 723 | sigemptyset(&mask); |
| 724 | @@ -658,7 +813,7 @@ |
| 725 | } |
| 726 | |
| 727 | } |
| 728 | - printf("terminating, %i\n",answer); |
| 729 | + syslog(LOG_NOTICE, "terminating, %i\n",answer); |
| 730 | if (kill(pid, SIGTERM)<0) |
| 731 | perror("mouseemu: termination of uinput handlers failed\n"); |
| 732 | |
| 733 | @@ -670,12 +825,14 @@ |
| 734 | |
| 735 | //strncpy(argv[0],"mouseemu",argv0size); |
| 736 | startops: |
| 737 | + |
| 738 | for (i=0; i<EVENT_DEVS; i++) { |
| 739 | eventdevs[i].handle = -1; |
| 740 | eventdevs[i].vendor = 0; |
| 741 | eventdevs[i].product= 0; |
| 742 | |
| 743 | ihandler[i].handler=0; |
| 744 | + ihandler[i].mode=0; |
| 745 | ihandler[i].fd=-1; |
| 746 | } |
| 747 | |
| 748 | @@ -685,28 +842,45 @@ |
| 749 | |
| 750 | running = uinput_setup(); |
| 751 | if (running < 0) { |
| 752 | - printf("mouseemu: Make sure uinput module is loaded or available " |
| 753 | - "in the kernel.\n"); |
| 754 | + fprintf(stderr, "No uinput device found! Make sure the uinput module is loaded\n" |
| 755 | + "or CONFIG_INPUT_UINPUT is compiled into the kernel.\n"); |
| 756 | } |
| 757 | |
| 758 | |
| 759 | chdir("/"); |
| 760 | - |
| 761 | + |
| 762 | + if (autorescan) |
| 763 | + alarm(5); |
| 764 | + |
| 765 | /*main loop*/ |
| 766 | |
| 767 | while(running > 0) { |
| 768 | |
| 769 | tv.tv_sec = 1; tv.tv_usec = 0; |
| 770 | maxfd = create_fdset(&inset); |
| 771 | - if ((val = select (maxfd+1, &inset, NULL, NULL, &tv)) >= 0) { |
| 772 | + val = select (maxfd+1, &inset, NULL, NULL, &tv); |
| 773 | + /* signal received, so rescan for devices when idle*/ |
| 774 | + if (val == 0 && rescan) { |
| 775 | + rescan = 0; |
| 776 | + rescan_devs(); |
| 777 | + } |
| 778 | + if (val >= 0) { |
| 779 | if (val == 0) |
| 780 | usleep(10); |
| 781 | - else |
| 782 | - call_inputhandler(&inset); |
| 783 | + else { |
| 784 | + if (errno == ENODEV) { |
| 785 | + debugf("device disconnect detected (select %d, errno %d), rescanning devices\n", val, errno); |
| 786 | + errno = 0; |
| 787 | + rescan_devs(); |
| 788 | + usleep(500); |
| 789 | + } else { |
| 790 | + call_inputhandler(&inset); |
| 791 | + } |
| 792 | + } |
| 793 | } |
| 794 | /* tell the parent we are running without problems */ |
| 795 | /* What should we do if the parent is dead? */ |
| 796 | - if (answer) { |
| 797 | + if (answer && !nofork) { |
| 798 | answer=0; |
| 799 | kill(getppid(), SIGUSR1); |
| 800 | } |
| 801 | diff -ruN mouseemu-orig/mouseemu.h mouseemu/mouseemu.h |
| 802 | --- mouseemu-orig/mouseemu.h 2005-03-30 08:41:00.000000000 +0200 |
| 803 | +++ mouseemu/mouseemu.h 2008-11-23 12:14:26.000000000 +0100 |
| 804 | @@ -33,6 +33,9 @@ |
| 805 | #define BTN2 0x04 |
| 806 | #define BTN3 0x02 |
| 807 | |
| 808 | +#define HANDLER_KEYBOARD (1 << 0) |
| 809 | +#define HANDLER_MOUSE (1 << 1) |
| 810 | + |
| 811 | /* device structure */ |
| 812 | typedef struct _kdev { |
| 813 | int handle; |
| 814 | @@ -42,11 +45,12 @@ |
| 815 | |
| 816 | /* handler structure */ |
| 817 | typedef struct _ihandler { |
| 818 | - void (*handler)(int fd); |
| 819 | + void (*handler)(int mode, int fd); |
| 820 | + int mode; |
| 821 | int fd; |
| 822 | int grab; |
| 823 | } input_handler; |
| 824 | |
| 825 | void unregister_inputhandler (int fd); |
| 826 | -int register_inputhandler(int fd, void (*func)(int fd), int grab); |
| 827 | +int register_inputhandler(int mode, int fd, void (*func)(int mode, int fd), int grab); |
| 828 | #endif |