File gpm-1.20.1-ps2_reconnection.patch of Package gpm

--- src/gpm.c
+++ src/gpm.c
@@ -71,7 +71,8 @@
       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;
@@ -329,25 +330,57 @@
  * fetch the actual device data from the mouse device, dependent on
  * what Gpm_Type is being passed.
  *-------------------------------------------------------------------*/
-static inline char *getMouseData(int fd, Gpm_Type *type, int kd_mode)
+static inline 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 ((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]&(m_type->proto)[0]) != (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 (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]);
@@ -357,6 +390,12 @@
       return NULL;
    }
 
+   if ((preread > howmany) &&
+       (kd_mode!=KD_TEXT && fifofd != -1 && opt_rawrep))
+      /* one byte was read in test for replugging sequence and will be
+         used as normal data byte */
+      write(fifofd, &(data[1]), 1);
+
 /*....................................... read the rest */
 
    /*
@@ -364,13 +403,20 @@
     * tried ps2 with the original selection package, which called usleep()
     */
      
-   if((i=m_type->packetlen-howmany)) /* still to get */
+   if((i=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 > 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));
@@ -396,7 +442,7 @@
  * the data via repeat_fun() to the repeater device
  *-------------------------------------------------------------------*/
 static inline int processMouse(int fd, Gpm_Event *event, Gpm_Type *type,
-                int kd_mode)
+                int kd_mode, unsigned char *save_byte, int *is_save_byte)
 {
    char *data;
    static int fine_dx, fine_dy;
@@ -408,6 +454,7 @@
    fd_set fdSet;
    static int newB=0, oldB=0, oldT=0; /* old buttons and Type to chain events */
    /* static int buttonlock, buttonlockflag; */
+   int restart;
 
 #define GET_TIME(tv) (gettimeofday(&tv, (struct timezone *)NULL))
 #define DIF_TIME(t1,t2) ((t2.tv_sec -t1.tv_sec) *1000+ \
@@ -433,8 +480,11 @@
       FD_ZERO(&fdSet); FD_SET(fd,&fdSet); i=0;
 
       do { /* cluster loop */
-         if(((data=getMouseData(fd,m_type,kd_mode))==NULL)
+         restart = 0;
+         if(((data=getMouseData(fd,m_type,kd_mode,
+	                        save_byte,is_save_byte,&restart))==NULL)
             || ((*(m_type->fun))(&nEvent,data)==-1) ) {
+            if (restart) return -1;
             if (!i) return 0;
             else break;
          }
@@ -916,6 +966,32 @@
    exit(0);
 }
 
+static inline void initMouse(int i, int *fd, int *maxfd)
+{
+  which_mouse=mouse_table+i; /* used to access options */
+
+  if (!opt_dev) gpm_report(GPM_PR_OOPS,GPM_MESS_NEED_MDEV);
+
+  if(!strcmp(opt_dev,"-")) *fd=0; /* use stdin */
+  else if( (*fd=open(opt_dev,O_RDWR | O_NDELAY)) < 0)
+    gpm_report(GPM_PR_OOPS,GPM_MESS_OPEN,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(opt_type, opt_options, &mouse_argc[i], ',');
+
+  /* init the device, and use the return value as new mouse type */
+  if (m_type->init)
+    m_type=(m_type->init)(*fd, m_type->flags, m_type, mouse_argc[i],
+    mouse_argv[i]);
+  if (!m_type) gpm_report(GPM_PR_OOPS,GPM_MESS_MOUSE_INIT);
+
+  which_mouse->fd=*fd;
+  *maxfd=max(*fd, *maxfd);
+}
+
 /*-------------------------------------------------------------------*/
 int old_main()
 {
@@ -928,28 +1004,7 @@
    Gpm_Event event;
 
    for (i = 1; i <= 1+opt_double; i++) {
-      which_mouse=mouse_table+i; /* used to access options */
-
-      if (!opt_dev) gpm_report(GPM_PR_OOPS,GPM_MESS_NEED_MDEV);
-
-      if(!strcmp(opt_dev,"-")) fd=0; /* use stdin */
-      else if( (fd=open(opt_dev,O_RDWR | O_NDELAY)) < 0)
-         gpm_report(GPM_PR_OOPS,GPM_MESS_OPEN,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(opt_type, opt_options, &mouse_argc[i], ',');
-
-      /* init the device, and use the return value as new mouse type */
-      if (m_type->init)
-         m_type=(m_type->init)(fd, m_type->flags, m_type, mouse_argc[i],
-         mouse_argv[i]);
-      if (!m_type) gpm_report(GPM_PR_OOPS,GPM_MESS_MOUSE_INIT);
-
-      which_mouse->fd=fd;
-      maxfd=max(fd, maxfd);
+     initMouse(i, &fd, &maxfd);
    }
 
 /*....................................... catch interesting signals */
@@ -1063,10 +1118,14 @@
  */
 
       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, m_type, kd_mode))
+	    rc = processMouse(which_mouse->fd, &event, 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
@@ -1075,7 +1134,15 @@
                (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 */
--- src/headers/gpmInt.h
+++ src/headers/gpmInt.h
@@ -142,6 +142,7 @@
 
   int (*repeat_fun)(Gpm_Event *state, int fd); /* repeat this event into fd */
                           /* itz Mon Jan 11 23:27:54 PST 1999 */
+  int isPS2;		  /* is 1 for PS/2 mouses, 0 otherwise */
 }                   Gpm_Type;
 
 #define GPM_EXTRA_MAGIC_1 0xAA
@@ -165,6 +166,8 @@
   char *opt_options; /* extra textual configuration */
   Gpm_Type *m_type;
   int fd;
+  unsigned char save_byte;
+  int is_save_byte;
 };
 
 extern struct mouse_features mouse_table[3], *which_mouse; /*the current one*/
--- src/headers/message.h
+++ src/headers/message.h
@@ -65,6 +65,7 @@
 #define GPM_MESS_VERSION            "gpm " GPM_RELEASE " (X-Mas), " GPM_RELEASE_DATE
 #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"
--- src/mice.c
+++ src/mice.c
@@ -2217,113 +2217,113 @@
 
    {"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},
 #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, 1},
 #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, 0},
+                                {0xf8, 0x80, 0x00, 0x00}, 3, 1, 0, 0, 0, 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}
 };
 
 /*------------------------------------------------------------------------*/
openSUSE Build Service is sponsored by