Index: src/mice.c =================================================================== --- src/mice.c.orig 2009-02-09 10:58:53.000000000 +0100 +++ src/mice.c 2010-09-08 18:38:24.516205731 +0200 @@ -2372,116 +2372,116 @@ Gpm_Type mice[]={ {"mman", "The \"MouseMan\" and similar devices (3/4 bytes per packet).", "Mouseman", M_mman, I_serial, CS7 | STD_FLG, /* first */ - {0x40, 0x40, 0x40, 0x00}, 3, 1, 1, 0, 0}, + {0x40, 0x40, 0x40, 0x00}, 3, 1, 1, 0, 0, 0}, {"ms", "The original ms protocol, with a middle-button extension.", "", M_ms, I_serial, CS7 | STD_FLG, - {0x40, 0x40, 0x40, 0x00}, 3, 1, 0, 0, 0}, + {0x40, 0x40, 0x40, 0x00}, 3, 1, 0, 0, 0, 0}, {"acecad", "Acecad tablet absolute mode(Sumagrapics MM-Series mode)", "", M_summa, I_summa, STD_FLG, - {0x80, 0x80, 0x00, 0x00}, 7, 1, 0, 1, 0}, + {0x80, 0x80, 0x00, 0x00}, 7, 1, 0, 1, 0, 0}, {"bare", "Unadorned ms protocol. Needed with some 2-buttons mice.", "Microsoft", M_bare, I_serial, CS7 | STD_FLG, - {0x40, 0x40, 0x40, 0x00}, 3, 1, 0, 0, 0}, + {0x40, 0x40, 0x40, 0x00}, 3, 1, 0, 0, 0, 0}, {"bm", "Micro$oft busmice and compatible devices.", "BusMouse", M_bm, I_empty, STD_FLG, /* bm is sun */ - {0xf8, 0x80, 0x00, 0x00}, 3, 3, 0, 0, 0}, + {0xf8, 0x80, 0x00, 0x00}, 3, 3, 0, 0, 0, 0}, {"brw", "Fellowes Browser - 4 buttons (and a wheel) (dual protocol?)", "", M_brw, I_pnp, CS7 | STD_FLG, - {0xc0, 0x40, 0xc0, 0x00}, 4, 1, 0, 0, 0}, + {0xc0, 0x40, 0xc0, 0x00}, 4, 1, 0, 0, 0, 0}, {"cal", "Calcomp UltraSlate", "", M_calus, I_calus, CS8 | CSTOPB | STD_FLG, - {0x80, 0x80, 0x80, 0x00}, 6, 6, 0, 1, 0}, + {0x80, 0x80, 0x80, 0x00}, 6, 6, 0, 1, 0, 0}, {"calr", "Calcomp UltraSlate - relative mode", "", M_calus_rel, I_calus, CS8 | CSTOPB | STD_FLG, - {0x80, 0x80, 0x80, 0x00}, 6, 6, 0, 0, 0}, + {0x80, 0x80, 0x80, 0x00}, 6, 6, 0, 0, 0, 0}, {"etouch", "EloTouch touch-screens (only button-1 events, by now)", "", M_etouch, I_etouch, STD_FLG, - {0xFF, 0x55, 0xFF, 0x54}, 7, 1, 0, 1, NULL}, + {0xFF, 0x55, 0xFF, 0x54}, 7, 1, 0, 1, NULL, 0}, #ifdef HAVE_LINUX_INPUT_H {"evdev", "Linux Event Device", "", M_evdev, I_empty, STD_FLG, - {0x00, 0x00, 0x00, 0x00} , 16, 16, 0, 0, NULL}, + {0x00, 0x00, 0x00, 0x00} , 16, 16, 0, 0, NULL, 0}, #endif /* HAVE_LINUX_INPUT_H */ {"exps2", "IntelliMouse Explorer (ps2) - 3 buttons, wheel unused", "ExplorerPS/2", M_imps2, I_exps2, STD_FLG, - {0xc0, 0x00, 0x00, 0x00}, 4, 1, 0, 0, 0}, + {0xc0, 0x00, 0x00, 0x00}, 4, 1, 0, 0, 0, 0}, #ifdef HAVE_LINUX_JOYSTICK_H {"js", "Joystick mouse emulation", "Joystick", M_js, NULL, 0, - {0xFC, 0x00, 0x00, 0x00}, 12, 12, 0, 0, 0}, + {0xFC, 0x00, 0x00, 0x00}, 12, 12, 0, 0, 0, 0}, #endif {"genitizer", "\"Genitizer\" tablet, in relative mode.", "", M_geni, I_serial, CS8|PARENB|PARODD, - {0x80, 0x80, 0x00, 0x00}, 3, 1, 0, 0, 0}, + {0x80, 0x80, 0x00, 0x00}, 3, 1, 0, 0, 0, 0}, {"gunze", "Gunze touch-screens (only button-1 events, by now)", "", M_gunze, I_gunze, STD_FLG, - {0xF9, 0x50, 0xF0, 0x30}, 11, 1, 0, 1, NULL}, + {0xF9, 0x50, 0xF0, 0x30}, 11, 1, 0, 1, NULL, 0}, {"imps2","Microsoft Intellimouse (ps2)-autodetect 2/3 buttons,wheel unused", "", M_imps2, I_imps2, STD_FLG, - {0xC0, 0x00, 0x00, 0x00}, 4, 1, 0, 0, R_imps2}, + {0xC0, 0x00, 0x00, 0x00}, 4, 1, 0, 0, R_imps2, 1}, {"logi", "Used in some Logitech devices (only serial).", "Logitech", M_logi, I_logi, CS8 | CSTOPB | STD_FLG, - {0xe0, 0x80, 0x80, 0x00}, 3, 3, 0, 0, 0}, + {0xe0, 0x80, 0x80, 0x00}, 3, 3, 0, 0, 0, 0}, {"logim", "Turn logitech into Mouse-Systems-Compatible.", "", M_logimsc, I_serial, CS8 | CSTOPB | STD_FLG, - {0xf8, 0x80, 0x00, 0x00}, 5, 1, 0, 0, 0}, + {0xf8, 0x80, 0x00, 0x00}, 5, 1, 0, 0, 0, 0}, {"mm", "MM series. Probably an old protocol...", "MMSeries", M_mm, I_serial, CS8 | PARENB|PARODD | STD_FLG, - {0xe0, 0x80, 0x80, 0x00}, 3, 1, 0, 0, 0}, + {0xe0, 0x80, 0x80, 0x00}, 3, 1, 0, 0, 0, 0}, {"ms3", "Microsoft Intellimouse (serial) - 3 buttons, wheel unused", "", M_ms3, I_pnp, CS7 | STD_FLG, - {0xc0, 0x40, 0xc0, 0x00}, 4, 1, 0, 0, R_ms3}, + {0xc0, 0x40, 0xc0, 0x00}, 4, 1, 0, 0, R_ms3, 0}, {"ms+", "Like 'ms', but allows dragging with the middle button.", "", M_ms_plus, I_serial, CS7 | STD_FLG, - {0x40, 0x40, 0x40, 0x00}, 3, 1, 0, 0, 0}, + {0x40, 0x40, 0x40, 0x00}, 3, 1, 0, 0, 0, 0}, {"ms+lr", "'ms+', but you can reset m by pressing lr (see man page).", "", M_ms_plus_lr, I_serial, CS7 | STD_FLG, - {0x40, 0x40, 0x40, 0x00}, 3, 1, 0, 0, 0}, + {0x40, 0x40, 0x40, 0x00}, 3, 1, 0, 0, 0, 0}, {"msc", "Mouse-Systems-Compatible (5bytes). Most 3-button mice.", "MouseSystems", M_msc, I_serial, CS8 | CSTOPB | STD_FLG, - {0xf8, 0x80, 0x00, 0x00}, 5, 1, 0, 0, R_msc}, + {0xf8, 0x80, 0x00, 0x00}, 5, 1, 0, 0, R_msc, 0}, {"mtouch", "MicroTouch touch-screens (only button-1 events, by now)", "", M_mtouch, I_mtouch, STD_FLG, - {0x80, 0x80, 0x80, 0x00}, 5, 1, 0, 1, NULL}, + {0x80, 0x80, 0x80, 0x00}, 5, 1, 0, 1, NULL, 0}, {"ncr", "Ncr3125pen, found on some laptops", "", M_ncr, NULL, STD_FLG, - {0x08, 0x08, 0x00, 0x00}, 7, 7, 0, 1, 0}, + {0x08, 0x08, 0x00, 0x00}, 7, 7, 0, 1, 0, 0}, {"netmouse","Genius NetMouse (ps2) - 2 buttons and 2 buttons 'up'/'down'.", "", M_netmouse, I_netmouse, CS7 | STD_FLG, - {0xc0, 0x00, 0x00, 0x00}, 4, 1, 0, 0, 0}, + {0xc0, 0x00, 0x00, 0x00}, 4, 1, 0, 0, 0, 1}, {"pnp", "Plug and pray. New mice may not run with '-t ms'.", "", M_bare, I_pnp, CS7 | STD_FLG, - {0x40, 0x40, 0x40, 0x00}, 3, 1, 0, 0, 0}, + {0x40, 0x40, 0x40, 0x00}, 3, 1, 0, 0, 0, 0}, {"ps2", "Busmice of the ps/2 series. Most busmice, actually.", "PS/2", M_ps2, I_ps2, STD_FLG, - {0xc0, 0x00, 0x00, 0x00}, 3, 1, 0, 0, R_ps2}, + {0xc0, 0x00, 0x00, 0x00}, 3, 1, 0, 0, R_ps2, 1}, {"sun", "'msc' protocol, but only 3 bytes per packet.", "", M_sun, I_serial, CS8 | CSTOPB | STD_FLG, - {0xf8, 0x80, 0x00, 0x00}, 3, 1, 0, 0, R_sun}, + {0xf8, 0x80, 0x00, 0x00}, 3, 1, 0, 0, R_sun, 0}, {"summa", "Summagraphics or Genius tablet absolute mode(MM-Series)", "", M_summa, I_summa, STD_FLG, - {0x80, 0x80, 0x00, 0x00}, 5, 1, 0, 1, R_summa}, + {0x80, 0x80, 0x00, 0x00}, 5, 1, 0, 1, R_summa, 0}, {"syn", "The \"Synaptics\" serial TouchPad.", "synaptics", M_synaptics_serial, I_serial, CS7 | STD_FLG, - {0x40, 0x40, 0x40, 0x00}, 6, 6, 1, 0, 0}, + {0x40, 0x40, 0x40, 0x00}, 6, 6, 1, 0, 0, 0}, {"synps2", "The \"Synaptics\" PS/2 TouchPad", "synaptics_ps2", M_synaptics_ps2, I_synps2, STD_FLG, - {0x80, 0x80, 0x00, 0x00}, 6, 1, 1, 0, 0}, + {0x80, 0x80, 0x00, 0x00}, 6, 1, 1, 0, 0, 1}, {"twid", "Twidddler keyboard", "", M_twid, I_twid, CS8 | STD_FLG, - {0x80, 0x00, 0x80, 0x80}, 5, 1, 0, 0, 0}, + {0x80, 0x00, 0x80, 0x80}, 5, 1, 0, 0, 0, 0}, {"vsxxxaa", "The DEC VSXXX-AA/GA serial mouse on DEC workstations.", "", M_vsxxx_aa, I_serial, CS8 | PARENB | PARODD | STD_FLG, - {0xe0, 0x80, 0x80, 0x00}, 3, 1, 0, 0, 0}, + {0xe0, 0x80, 0x80, 0x00}, 3, 1, 0, 0, 0, 0}, {"wacom","Wacom Protocol IV Tablets: Pen+Mouse, relative+absolute mode", "", M_wacom, I_wacom, STD_FLG, - {0x80, 0x80, 0x80, 0x00}, 7, 1, 0, 0, 0}, + {0x80, 0x80, 0x80, 0x00}, 7, 1, 0, 0, 0, 0}, {"wp", "Genius WizardPad tablet", "wizardpad", M_wp, I_wp, STD_FLG, - {0xFA, 0x42, 0x00, 0x00}, 10, 1, 0, 1, 0}, + {0xFA, 0x42, 0x00, 0x00}, 10, 1, 0, 1, 0, 0}, {"", "", "", NULL, NULL, 0, - {0x00, 0x00, 0x00, 0x00}, 0, 0, 0, 0, 0} + {0x00, 0x00, 0x00, 0x00}, 0, 0, 0, 0, 0, 0} }; /*------------------------------------------------------------------------*/ Index: src/daemon/getmousedata.c =================================================================== --- src/daemon/getmousedata.c.orig 2010-09-08 18:11:41.925698527 +0200 +++ src/daemon/getmousedata.c 2010-09-08 18:39:50.210572313 +0200 @@ -33,25 +33,58 @@ * fetch the actual device data from the mouse device, dependent on * what Gpm_Type is being passed. *-------------------------------------------------------------------*/ -char *getMouseData(int fd, Gpm_Type *type, int kd_mode) +char *getMouseData(int fd, Gpm_Type *type, int kd_mode, + unsigned char *save_byte , int *is_save_byte, int *restart) { static unsigned char data[32]; /* quite a big margin :) */ char *edata=data+type->packetlen; int howmany=type->howmany; + int preread; int i,j; /*....................................... read and identify one byte */ if (read(fd, data, howmany)!=howmany) { - if (opt_test) exit(0); - gpm_report(GPM_PR_ERR,GPM_MESS_READ_FIRST, strerror(errno)); - return NULL; + preread = 0; + if (*is_save_byte) { + /* one byte is saved, howmany must be 1 otherwise this + byte hasn't been saved */ + data[0] = *save_byte; + *is_save_byte = 0; + preread = 1; + } else { + if ((preread = read(fd, data, howmany))!=howmany) { + if (opt_test) exit(0); + gpm_report(GPM_PR_ERR,GPM_MESS_READ_FIRST, strerror(errno)); + return NULL; + } + } + } + + /* try to find sequence AA 00 which is generated by kernel-2.4.9 or higher + when PS/2 mouse was replugged */ + if (((which_mouse->m_type)->isPS2 == 1) && (data[0] == 0xaa)) { + if (preread == 1) { + // read second byte + if (read(fd, &(data[1]),1) == 1) + preread += 1; + } + if ((preread >= 2) && (data[1] == 0x0)) { + gpm_report(GPM_PR_DEBUG,GPM_MESS_REPLUGGED); + *restart = 1; + return NULL; + } } if (kd_mode!=KD_TEXT && fifofd != -1 && opt_rawrep) write(fifofd, data, howmany); if ((data[0]&((which_mouse->m_type)->proto)[0]) != ((which_mouse->m_type)->proto)[1]) { + if (preread > howmany) { + /* second byte was involuntary preread in test for PS/2 replugging */ + *save_byte = data[1]; + *is_save_byte = 1; + } if ((which_mouse->m_type)->getextra == 1) { data[1]=GPM_EXTRA_MAGIC_1; data[2]=GPM_EXTRA_MAGIC_2; gpm_report(GPM_PR_DEBUG,GPM_EXTRA_DATA,data[0]); @@ -68,13 +101,20 @@ char *getMouseData(int fd, Gpm_Type *typ * tried ps2 with the original selection package, which called usleep() */ - if((i=(which_mouse->m_type)->packetlen-howmany)) /* still to get */ + if((i=(which_mouse->m_type)->packetlen-preread) > 0) { /* still to get */ do { j = read(fd,edata-i,howmany); /* edata is pointer just after data */ if (kd_mode!=KD_TEXT && fifofd != -1 && opt_rawrep && j > 0) write(fifofd, edata-i, j); i -= j; } while (i && j); + } else { + if (preread > (which_mouse->m_type)->packetlen) { + /* second byte was involuntary preread in test for PS/2 replugging */ + *save_byte = data[1]; + *is_save_byte = 1; + } + } if (i) { gpm_report(GPM_PR_ERR,GPM_MESS_READ_REST, strerror(errno)); Index: src/daemon/gpm.c =================================================================== --- src/daemon/gpm.c.orig 2009-02-09 10:58:53.000000000 +0100 +++ src/daemon/gpm.c 2010-09-08 18:38:23.256288409 +0200 @@ -73,7 +73,8 @@ struct mouse_features mouse_table[3] = { DEF_TIME, DEF_CLUSTER, DEF_THREE, DEF_GLIDEPOINT_TAP, (char *)NULL /* extra */, (Gpm_Type *)NULL, - -1 + -1, + 0, 0 /* save byte, is_save_byte */ } }; struct mouse_features *which_mouse; Index: src/daemon/old_main.c =================================================================== --- src/daemon/old_main.c.orig 2009-02-09 10:58:53.000000000 +0100 +++ src/daemon/old_main.c 2010-09-08 19:34:22.279958939 +0200 @@ -37,6 +37,38 @@ #define max(a,b) ((a)>(b) ? (a) : (b)) #endif +static inline void initMouse(int i, int *fd, int *maxfd) +{ + which_mouse=mouse_table+i; /* used to access options */ + + if (!(which_mouse->opt_dev)) + gpm_report(GPM_PR_OOPS,GPM_MESS_NEED_MDEV); + + if(!strcmp((which_mouse->opt_dev),"-")) + *fd=0; /* use stdin */ + else if( (*fd=open((which_mouse->opt_dev),O_RDWR | O_NDELAY)) < 0) + gpm_report(GPM_PR_OOPS,GPM_MESS_OPEN,(which_mouse->opt_dev)); + + /* and then reset the flag */ + fcntl(*fd,F_SETFL,fcntl(*fd,F_GETFL) & ~O_NDELAY); + + /* create argc and argv for this device */ + mouse_argv[i] = build_argv((which_mouse->opt_type), + (which_mouse->opt_options), + &mouse_argc[i], ','); + + /* init the device, and use the return value as new mouse type */ + if ((which_mouse->m_type)->init) + (which_mouse->m_type)=((which_mouse->m_type)->init)(*fd, (which_mouse->m_type)->flags, + (which_mouse->m_type), + mouse_argc[i], mouse_argv[i]); + + if (!(which_mouse->m_type)) gpm_report(GPM_PR_OOPS,GPM_MESS_MOUSE_INIT); + + which_mouse->fd=*fd; + *maxfd=max(*fd, *maxfd); +} + int old_main() { @@ -48,30 +80,8 @@ int old_main() int pending; Gpm_Event event; - for (i = 1; i <= 1+opt_double; i++) { - which_mouse=mouse_table+i; /* used to access options */ - - if (!(which_mouse->opt_dev)) gpm_report(GPM_PR_OOPS,GPM_MESS_NEED_MDEV); - - if(!strcmp((which_mouse->opt_dev),"-")) fd=0; /* use stdin */ - else if( (fd=open((which_mouse->opt_dev),O_RDWR | O_NDELAY)) < 0) - gpm_report(GPM_PR_OOPS,GPM_MESS_OPEN,(which_mouse->opt_dev)); - - /* and then reset the flag */ - fcntl(fd,F_SETFL,fcntl(fd,F_GETFL) & ~O_NDELAY); - - /* create argc and argv for this device */ - mouse_argv[i] = build_argv((which_mouse->opt_type), (which_mouse->opt_options), &mouse_argc[i], ','); - - /* init the device, and use the return value as new mouse type */ - if ((which_mouse->m_type)->init) - (which_mouse->m_type)=((which_mouse->m_type)->init)(fd, (which_mouse->m_type)->flags, (which_mouse->m_type), mouse_argc[i], - mouse_argv[i]); - if (!(which_mouse->m_type)) gpm_report(GPM_PR_OOPS,GPM_MESS_MOUSE_INIT); - - which_mouse->fd=fd; - maxfd=max(fd, maxfd); - } + for (i = 1; i <= 1+opt_double; i++) + initMouse(i, &fd, &maxfd); /*....................................... catch interesting signals */ @@ -184,10 +194,14 @@ int old_main() */ for (i=1; i <= 1+opt_double; i++) { + int rc; which_mouse=mouse_table+i; /* used to access options */ if (FD_ISSET(which_mouse->fd,&selSet)) { FD_CLR(which_mouse->fd,&selSet); pending--; - if (processMouse(which_mouse->fd, &event, (which_mouse->m_type), kd_mode)) + rc = processMouse(which_mouse->fd, &event, (which_mouse->m_type), + kd_mode, &(which_mouse->save_byte), + &(which_mouse->is_save_byte)); + if (rc > 0) { /* pass it to the client, if any * or to the default handler, if any * or to the selection handler @@ -196,7 +210,15 @@ int old_main() (cinfo[event.vc] && do_client(cinfo[event.vc], &event)) || (cinfo[0] && do_client(cinfo[0], &event)) || do_selection(&event); + } else if (rc == -1) { + /* try to reinitialise the mouse */ + FD_CLR(which_mouse->fd, &selSet); + close(which_mouse->fd); + initMouse(i, &fd, &maxfd); + FD_CLR(which_mouse->fd, &selSet); + which_mouse->is_save_byte=0; } + } } /*..................... got connection, process it */ Index: src/daemon/processmouse.c =================================================================== --- src/daemon/processmouse.c.orig 2009-02-09 10:58:53.000000000 +0100 +++ src/daemon/processmouse.c 2010-09-08 18:11:42.105686598 +0200 @@ -40,7 +40,8 @@ (t2.tv_usec-t1.tv_usec)/1000) -int processMouse(int fd, Gpm_Event *event, Gpm_Type *type, int kd_mode) +int processMouse(int fd, Gpm_Event *event, Gpm_Type *type, int kd_mode, + unsigned char *save_byte, int *is_save_byte) { char *data; static int fine_dx, @@ -55,6 +56,7 @@ int processMouse(int fd, Gpm_Event *even static struct timeval tv1={0,0}, tv2; /* tv1==0: first click is single */ static struct timeval timeout={0,0}; fd_set fdSet; + int restart; oldT = event->type; @@ -78,9 +80,12 @@ int processMouse(int fd, Gpm_Event *even FD_SET(fd,&fdSet); do { /* cluster loop */ - if(((data=getMouseData(fd, (which_mouse->m_type), kd_mode)) == NULL) + restart = 0; + if(((data=getMouseData(fd, (which_mouse->m_type), kd_mode, + save_byte,is_save_byte,&restart)) == NULL) || ((*((which_mouse->m_type)->fun))(&nEvent,data)==-1) ) { - + + if (restart) return -1; if (!i) { return 0; } else { Index: src/headers/daemon.h =================================================================== --- src/headers/daemon.h.orig 2009-02-09 10:58:53.000000000 +0100 +++ src/headers/daemon.h 2010-09-08 19:26:01.901761337 +0200 @@ -76,6 +76,7 @@ typedef struct Gpm_Type { /* repeat this event into fd */ int (*repeat_fun)(Gpm_Event *state, int fd); + int isPS2; /* 1 for PS/2 mouses, 0 otherwise */ } Gpm_Type; /* this structure is used to hide the dual-mouse stuff */ @@ -96,6 +97,8 @@ struct mouse_features { char *opt_options; /* extra textual configuration */ Gpm_Type *m_type; int fd; + unsigned char save_byte; + int is_save_byte; }; /************************************************************************* @@ -197,7 +200,9 @@ int do_selection(Gpm_Event *event); void get_console_size(Gpm_Event *ePtr); int get_data(Gpm_Connect *where, int whence); -char *getMouseData(int fd, Gpm_Type *type, int kd_mode); +char *getMouseData(int fd, Gpm_Type *type, int kd_mode, + unsigned char *save_byte , int *is_save_byte, + int *restart); int getsym(const unsigned char *p0, unsigned char *res); void gpm_exited(void); @@ -207,7 +212,8 @@ int open_console(const int mode); int old_main(); int processConn(int fd); -int processMouse(int fd, Gpm_Event *event, Gpm_Type *type, int kd_mode); +int processMouse(int fd, Gpm_Event *event, Gpm_Type *type, int kd_mode, + unsigned char *save_byte, int *is_save_byte); int processRequest(Gpm_Cinfo *ci, int vc); int processSpecial(Gpm_Event *event); Index: src/headers/message.h =================================================================== --- src/headers/message.h.orig 2009-02-09 10:58:53.000000000 +0100 +++ src/headers/message.h 2010-09-08 18:38:24.516205731 +0200 @@ -65,6 +65,7 @@ #define GPM_MESS_VERSION "gpm " PACKAGE_VERSION #define GPM_MESS_STARTED "Started gpm successfully. Entered daemon mode." #define GPM_MESS_KILLED "Killed gpm(%d)." +#define GPM_MESS_REPLUGGED "Mouse was replugged" #define GPM_MESS_SKIP_DATA "Skipping a data packet (?)" #define GPM_MESS_DATA_4 "Data %02x %02x %02x (%02x)" #define GPM_MESS_NO_MAGIC "No magic"