#! /bin/sh /usr/share/dpatch/dpatch-run ## 61_rescan.dpatch.dpatch by Michael Schmitz <schmitz@biophys.uni-duesseldorf.de> ## ## All lines beginning with `## DP:' are a description of the patch. ## DP: rescan event devices on disconnects diff -urNad mouseemu-0.15-3~/mouseemu.8 mouseemu-0.15-3/mouseemu.8 --- mouseemu-0.15-3~/mouseemu.8 2006-03-14 01:42:14.332625933 +0100 +++ mouseemu-0.15-3/mouseemu.8 2006-03-14 01:43:55.000000000 +0100 @@ -52,13 +52,20 @@ .B -nofork don't run in the background .TP +.B -autorescan +Automatically scan every 5s for new devices. This is normally not need, as udev should +inform mouseemu about new devices. +.TP .B -help show usage message .PP The key codes for the buttons and modifiers are key scancodes. They can be found in include/linux/input.h in the kernel headers or by using `showkey` in a console. The keycodes must be given as decimal values (`showkey` displays hex values!). - +.PP +Mouseemu does normally not automatically scan for new devices. An udev rule is used +to trigger a rescan when new devices are connected. You can also trigger a rescan +manually by sending a HUP signal to the mouseemu process. .SH EXAMPLES .PP To have the same behaviour as in MacOS X (CTRL-click for right mouse button and no @@ -69,7 +76,12 @@ .RE .PP The code for the (left) mouse button is 272 (0x110 in hex). The code for CTRL is 29. - +.PP +Trigger a rescan for newly attached devices: +.PP +.RS 4 +.B kill -HUP `cat /var/run/mouseemu.pid` +.RE .SH AUTHOR Mouseemu was written by Colin Leroy .nh diff -urNad mouseemu-0.15-3~/mouseemu.c mouseemu-0.15-3/mouseemu.c --- mouseemu-0.15-3~/mouseemu.c 2006-03-14 01:42:14.284625933 +0100 +++ mouseemu-0.15-3/mouseemu.c 2006-03-14 01:42:14.000000000 +0100 @@ -19,6 +19,7 @@ #include <stdio.h> #include <stdlib.h> #include <unistd.h> +#include <errno.h> #include <fcntl.h> #include <string.h> #include <signal.h> @@ -47,12 +48,14 @@ static int running = -1; volatile sig_atomic_t answer = 1; +volatile sig_atomic_t rescan = 0; pid_t pid = -1; -#define EVENT_DEVS 6 +#define EVENT_DEVS 32 static kdev eventdevs[EVENT_DEVS]; static input_handler ihandler[EVENT_DEVS]; - +static int debug = 0; +static int autorescan = 0; static void send_event(int fd, int type, int code, int value) { @@ -242,12 +245,18 @@ ioctl(fd, EVIOCGBIT(0, EV_MAX), bit); if (test_bit(EV_KEY, bit) && test_bit(EV_REP, bit)) { ioctl(fd, EVIOCGID, id); + /* our own virtual keyboard (on rescans)*/ + if (id[ID_PRODUCT] == 0x1F && id[ID_VENDOR] == 0x1F) { + close(fd); + continue; + } if (id[ID_PRODUCT] != eventdevs[m].product || id[ID_VENDOR] != eventdevs[m].vendor) { if (eventdevs[m].handle >= 0) { unregister_inputhandler(eventdevs[m].handle); close(eventdevs[m].handle); } + if (debug) fprintf(stderr, "keyboard: fd %d event%d, vendor %4x product %4x\n", fd, n, id[ID_VENDOR], id[ID_PRODUCT]); eventdevs[m].handle= fd; eventdevs[m].product = id[ID_PRODUCT]; eventdevs[m].vendor = id[ID_VENDOR]; @@ -256,12 +265,18 @@ m++; } else if (test_bit(EV_REL, bit)) { ioctl(fd, EVIOCGID, id); + /* our own virtual mouse (on rescans)*/ + if (id[ID_PRODUCT] == 0x1E && id[ID_VENDOR] == 0x1F) { + close(fd); + continue; + } if (id[ID_PRODUCT] != eventdevs[m].product || id[ID_VENDOR] != eventdevs[m].vendor) { if (eventdevs[m].handle >= 0) { unregister_inputhandler(eventdevs[m].handle); close(eventdevs[m].handle); } + if (debug) fprintf(stderr, "mouse : fd %d event%d, vendor %4x product %4x\n", fd, n, id[ID_VENDOR], id[ID_PRODUCT]); eventdevs[m].handle= fd; eventdevs[m].product = id[ID_PRODUCT]; eventdevs[m].vendor = id[ID_VENDOR]; @@ -279,6 +294,24 @@ } } +void rescan_devs() +{ + int i, cfd; + + for (i=0; i<EVENT_DEVS; i++) { + if (ihandler[i].fd != -1) { + cfd=ihandler[i].fd; + unregister_inputhandler(ihandler[i].fd); + close(cfd); + } + eventdevs[i].product = 0; + eventdevs[i].vendor = 0; + eventdevs[i].handle = -1; + } + usleep(100); + scan_for_devs(); +} + int register_inputhandler (int fd, void (*func)(int fd), int grab) { int n; @@ -318,7 +351,7 @@ FD_ZERO(watchset); for (maxfd=n=0; n < EVENT_DEVS; n++) { - if (ihandler[n].fd == -1) break; + if (ihandler[n].fd == -1) continue; FD_SET(ihandler[n].fd, watchset); if (ihandler[n].fd > maxfd) maxfd = ihandler[n].fd; @@ -331,7 +364,7 @@ int n; for (n=0; n < EVENT_DEVS; n++) { - if (ihandler[n].fd == -1) break; + if (ihandler[n].fd == -1) continue; if (FD_ISSET(ihandler[n].fd, inset)) ihandler[n].handler (ihandler[n].fd); } @@ -479,7 +512,7 @@ void uinput_cleanup() { - int i; + int i, cfd; printf("mouseemu: cleaning...\n"); @@ -488,8 +521,9 @@ for (i=0; i<EVENT_DEVS; i++) { if (ihandler[i].fd != -1) { + cfd=ihandler[i].fd; unregister_inputhandler(ihandler[i].fd); - close(ihandler[i].fd); + close(cfd); } } @@ -507,6 +541,11 @@ { if (sig_num == SIGUSR1) { answer = 1; + } else if (sig_num == SIGHUP) { + rescan = 1; + } else if (sig_num == SIGALRM) { + rescan = 1; + alarm(5); } else { //printf("mouseemu: aborting on sig %i \n",sig_num); /*terminate the parent:*/ @@ -530,10 +569,13 @@ /*SIGUSR1 for process communication *SIGTERM and SIGCHLD for quitting + *SIGHUP and SIGALRM for rescaning devices */ sigaction(SIGUSR1, &usr_action, NULL); sigaction(SIGTERM, &usr_action, NULL); + sigaction(SIGHUP, &usr_action, NULL); sigaction(SIGCHLD, &usr_action, NULL); + sigaction(SIGALRM, &usr_action, NULL); sigprocmask(SIG_UNBLOCK, &mask, 0); @@ -547,7 +589,8 @@ "\t[-scroll SCROLL_MOD]\n" "\t[-typing-block DELAY]\n" "\t[-device UINPUT_DEVICE]\n" - "\t[-nofork]\n", + "\t[-nofork]\n" + "\t[-autorescan]\n", argv[0]); fprintf(stream, "All modifier and button key arguments are\n" "key scancodes. They can be found in \n" @@ -637,6 +680,11 @@ nofork=1; i += 1; continue; + } + else if (!strcmp(argv[i], "-autorescan")) { + autorescan=1; + i += 1; + continue; } else { usage(stderr, argv); } @@ -709,6 +757,9 @@ //strncpy(argv[0],"mouseemu",argv0size); startops: + if (nofork) + debug = 1; + for (i=0; i<EVENT_DEVS; i++) { eventdevs[i].handle = -1; eventdevs[i].vendor = 0; @@ -730,18 +781,35 @@ chdir("/"); - + + if (autorescan) + alarm(5); + /*main loop*/ while(running > 0) { tv.tv_sec = 1; tv.tv_usec = 0; maxfd = create_fdset(&inset); - if ((val = select (maxfd+1, &inset, NULL, NULL, &tv)) >= 0) { + val = select (maxfd+1, &inset, NULL, NULL, &tv); + /* signal received, so rescan for devices when idle*/ + if (val == 0 && rescan) { + rescan = 0; + rescan_devs(); + } + if (val >= 0) { if (val == 0) usleep(10); - else - call_inputhandler(&inset); + else { + if (errno == ENODEV) { + if (debug) fprintf(stderr, "select returned %d, errno %d, rescanning devices\n", val, errno); + errno = 0; + rescan_devs(); + usleep(500); + } else { + call_inputhandler(&inset); + } + } } /* tell the parent we are running without problems */ /* What should we do if the parent is dead? */