--- gpm.c
+++ gpm.c
@@ -321,7 +321,7 @@
 /*-------------------------------------------------------------------*/
 /*-------------------------------------------------------------------*/
 /*-------------------------------------------------------------------*/
-static inline char *getMouseData(int fd, Gpm_Type *type, int kd_mode)
+static inline char *getMouseData(int fd, Gpm_Type *type, int kd_mode, int *restart)
 {
   static unsigned char data[32]; /* quite a big margin :) */
   char *edata=data+type->packetlen;
@@ -336,6 +336,22 @@
       return NULL;
       }
 
+    if (data[0] == 0xaa) {
+      j=read(fd,&(data[1]),2);
+      if ((j < 1) || (data[1] != 0x0)) {
+        if (m_type->getextra) {
+	  data[1]=GPM_EXTRA_MAGIC_1; data[2]=GPM_EXTRA_MAGIC_2;
+          gpm_debug_log(LOG_DEBUG,"Extra %02x",data[0]);
+	  return data;
+	}
+        gpm_debug_log(LOG_DEBUG,"Error in protocol");
+        return NULL;
+      }
+      gpm_debug_log(LOG_DEBUG,"Mouse was replugged");
+      *restart = 1;   
+      return NULL;
+    }
+
       if (kd_mode!=KD_TEXT && fifofd != -1 && opt_rawrep)
 	write(fifofd, data, howmany);
 
@@ -402,6 +418,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+ \
@@ -432,9 +449,11 @@
 
     do /* cluster loop */
       {
-      if (   ((data=getMouseData(fd,m_type,kd_mode))==NULL)
+      restart = 0;
+      if (   ((data=getMouseData(fd,m_type,kd_mode,&restart))==NULL)
 	  || ((*(m_type->fun))(&nEvent,data)==-1) )
 	{
+	if (restart) return -1;
 	if (!i) return 0;
 	else break;
 	}
@@ -926,6 +945,40 @@
   unlink(GPM_NODE_CTL);
 }
 
+static inline int initMouse(int i, int *fd, int *maxfd)                        
+{
+  which_mouse=mouse_table+i; /* used to access options */
+
+  /* open the device with ndelay, to catch a locked device */
+  if (opt_dev)
+    {
+      if (!strcmp(opt_dev,"-"))
+        *fd=0;
+      else if ((*fd=open(opt_dev,O_RDWR | O_NDELAY))<0)
+        { oops(opt_dev); }
+    }
+  else /* use "/dev/mouse" */
+    {
+      opt_dev = "/dev/mouse";
+      if ((*fd=open(opt_dev,O_RDWR | O_NDELAY))<0)
+        { oops(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)
+    { oops("mouse initialization failed"); }
+
+  which_mouse->fd=*fd;
+  *maxfd=max(*fd, *maxfd);
+} 
+
 /*-------------------------------------------------------------------*/
 int main(int argc, char **argv)
 {
@@ -951,38 +1004,7 @@
 
   for (i=1; i <= 1+opt_double; i++)
     {
-      which_mouse=mouse_table+i; /* used to access options */
-
-      /* open the device with ndelay, to catch a locked device */
-      if (opt_dev)
-        {
-          if (!strcmp(opt_dev,"-"))
-            fd=0;
-          else if ((fd=open(opt_dev,O_RDWR | O_NDELAY))<0)
-            { oops(opt_dev); }
-        }
-      else /* use "/dev/mouse" */
-        {
-          opt_dev = "/dev/mouse";
-          if ((fd=open(opt_dev,O_RDWR | O_NDELAY))<0)
-            { oops(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)
-        { oops("mouse initialization failed"); }
-
-      which_mouse->fd=fd;
-      maxfd=max(fd, maxfd);
+      initMouse(i, &fd, &maxfd);
     } /*for*/
 
   /* FIXME: stderr must be closed at this point, as protocol init needs it */
@@ -1114,11 +1136,13 @@
 
     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);
+	  if (rc > 0) {
 	    /*
 	     * pass it to the client, if any
 	     * or to the default handler, if any
@@ -1127,6 +1151,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);
+            }
 	  }
       }
 
