Subversion Repository

Parent Directory Parent Directory | Revision Log Revision Log


Revision 369 - (show annotations)
Sun Oct 4 15:02:55 2009 UTC (3 years, 7 months ago) by cjg
File size: 23058 byte(s)
mouseemu: fixed Gennaro's wrong fix
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